Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/339.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/django/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何在从数据库加载大数据并转换为JSON时提高性能_Python_Django_Json_Python 2.7_Django Models - Fatal编程技术网

Python 如何在从数据库加载大数据并转换为JSON时提高性能

Python 如何在从数据库加载大数据并转换为JSON时提高性能,python,django,json,python-2.7,django-models,Python,Django,Json,Python 2.7,Django Models,我写了一个Djano应用程序,它处理财务数据处理。 我必须从MySQL表中加载大数据(超过1000000条记录),并在django视图中将记录转换为JSON数据,如下所示: trades = MtgoxTrade.objects.all() data = [] for trade in trades: js = dict() js['time']= trade.time js['price']= trade.price

我写了一个Djano应用程序,它处理财务数据处理。 我必须从MySQL表中加载大数据(超过1000000条记录),并在django视图中将记录转换为JSON数据,如下所示:

trades = MtgoxTrade.objects.all()
data = []
for trade in trades:
            js = dict()
            js['time']= trade.time
            js['price']= trade.price
            js['amount']= trade.amount
            js['type']= trade.type
            data.append(js)
return data
import time

ts = time.time()
data = list()
for i in range(1000000):
    d = {}
    d['a'] = 1
    d['b'] = 2
    d['c'] = 3
    d['d'] = 4
    d['a'] = 5
    data.append(d)

print(time.time() - ts)



/opt/python-3.3.0/bin/python3 foo2.py 
0.5906929969787598

python2.6 foo2.py 
1.74390792847

python2.7 foo2.py 
0.673550128937
问题是FOR循环非常慢(200000条记录需要9秒以上),有没有有效的方法在Python中将DB记录转换为JSON格式的数据

更新:我已经根据Mike Housky在我的ENV(ActivePython2.7,Win7)中的回答运行了代码,并对代码进行了更改,结果是

def create_data(n):
    from api.models import MtgoxTrade
    result = MtgoxTrade.objects.all()

    return result


  Build ............ 0.330999851227
  For loop ......... 7.98400020599
  List Comp. ....... 0.457000017166
  Ratio ............ 0.0572394796312
  For loop 2 ....... 0.381999969482
  Ratio ............ 0.047845686326
你会发现for循环大约需要8秒!如果我注释掉For循环,那么List Comp也需要这样的时间:

Times:
  Build ............ 0.343000173569
  List Comp. ....... 7.57099986076
  For loop 2 ....... 0.375999927521

我的新问题是for循环是否会触及数据库?但我没有看到任何数据库访问日志。真奇怪

您可以使用列表理解,因为它可以防止许多
dict()
append()
调用:

trades = MtgoxTrade.objects.all()
data = [{'time': trade.time, 'price': trade.price, 'amount': trade.amount, 'type': trade.type}
        for trade in trades]
return data

函数调用在Python中非常昂贵,因此您应该尽量避免在慢循环中调用函数。

以下是一些可以尝试的技巧/事项

由于最终需要从queryset生成JSON字符串,请使用django的内置:

通过使用或模块,可以加快序列化速度。请参阅设置

此外,不要从记录中获取所有字段值,而是显式地获取需要序列化的内容:

MtgoxTrade.objects.all().values('time','price','amount','type')
此外,您可能希望使用queryset的方法:

…对于返回大量您需要的对象的QuerySet 只需要访问一次,这样可以获得更好的性能和 显著减少记忆

此外,您还可以将庞大的queryset拆分为多个批次,请参见:

另见:


首先,您必须检查从数据库或循环中获取数据时是否发生性能损失

没有真正的选项可以给你显著的加速-也没有使用上面提到的列表理解

然而,Python2和Python3在性能上存在巨大差异

一个简单的基准测试向我表明,使用Python3.3时,for循环的速度大约快2.5倍(使用以下一些简单的基准测试):


您还将注意到,Python 2.6和2.7之间存在显著的性能差异。

这个答案支持Simeon Visser的观察。我运行了以下代码:

import gc, random, time
if "xrange" not in dir(__builtins__):
    xrange = range

class DataObject(object):
    def __init__(self, time, price, amount, type):
        self.time = time
        self.price = price
        self.amount = amount
        self.type = type

def create_data(n):
    result = []
    for index in xrange(n):
        s = str(index);
        result.append(DataObject("T"+s, "P"+s, "A"+s, "ty"+s))
    return result

def convert1(trades):
    data = []
    for trade in trades:
                js = dict()
                js['time']= trade.time
                js['price']= trade.price
                js['amount']= trade.amount
                js['type']= trade.type
                data.append(js)
    return data

def convert2(trades):
    data = [{'time': trade.time, 'price': trade.price, 'amount': trade.amount, 'type': trade.type}
        for trade in trades]
    return data

def convert3(trades):
    ndata = len(trades)
    data = ndata*[None]
    for index in xrange(ndata):
        t = trades[index]
        js = dict()
        js['time']= t.time
        js['price']= t.price
        js['amount']= t.amount
        js['type']= t.type
        #js = {"time" : t.time, "price" : t.price, "amount" : t.amount, "type" : t.type}
    return data

def main(n=1000000):

    t0s = time.time()
    trades = create_data(n);
    t0f = time.time()
    t0 = t0f - t0s

    gc.disable()

    t1s = time.time()
    jtrades1 = convert1(trades)
    t1f = time.time()
    t1 = t1f - t1s

    t2s = time.time()
    jtrades2 = convert2(trades)
    t2f = time.time()
    t2 = t2f - t2s

    t3s = time.time()
    jtrades3 = convert3(trades)
    t3f = time.time()
    t3 = t3f - t3s

    gc.enable()

    print ("Times:")
    print ("  Build ............ " + str(t0))
    print ("  For loop ......... " + str(t1))
    print ("  List Comp. ....... " + str(t2))
    print ("  Ratio ............ " + str(t2/t1))
    print ("  For loop 2 ....... " + str(t3))
    print ("  Ratio ............ " + str(t3/t1))

main()
Win7、Core 2 Duo 3.0GHz上的结果: Python 2.7.3:

Times:
  Build ............ 2.95600008965
  For loop ......... 0.699999809265
  List Comp. ....... 0.512000083923
  Ratio ............ 0.731428890618
  For loop 2 ....... 0.609999895096
  Ratio ............ 0.871428659011
Python 3.3.0:

Times:
  Build ............ 3.4320058822631836
  For loop ......... 1.0200011730194092
  List Comp. ....... 0.7500009536743164
  Ratio ............ 0.7352942070195492
  For loop 2 ....... 0.9500019550323486
  Ratio ............ 0.9313733946208623
即使禁用了GC,它们也会有一些变化(启用GC时变化更大,但结果大致相同)。第三个转换计时显示,节省的时间中有相当大的一部分来自一百万次不调用.append()


忽略“For循环2”次。这个版本有一个bug,我现在没有时间修复它。

我认为尝试对数据库进行原始查询是值得的,因为模型将大量额外的样板代码放入字段(我相信字段就是属性),并且像前面提到的函数调用一样,代价高昂。请参阅,页面底部有一个示例,使用dictfetchall,这似乎是您要查找的内容。

您可能需要查看。它将返回dicts的iterable,而不是model对象,因此您不必创建大量中间数据结构。你的代码可以简化为

return MtgoxTrade.objects.values('time', 'price', 'amount', 'type')

在这里,列表理解不会给您带来任何显著的加速。可能这取决于实现。在Win7、CPython2.7.3和3.3.0上,我看到for循环中的列表理解能力提高了25%或更多。我会在回答中发布代码。你可以从另一个角度看问题。您可以使用芹菜来异步执行所有昂贵的任务芹菜对异步编程很有好处,但我的案例现在更喜欢同步设计,以后可能会检查:)谢谢~Set
DEBUG=False
并重试。@Burhan Khalid,DEBUG=False无法解决问题。我使用Python2.7,您的示例代码运行不到1秒,虽然我的循环仅在200000条记录下运行了8秒以上?但这在使用
GeometryField
时似乎不起作用。我使用过django序列化程序,但似乎也没有提高性能。而我的MtgoxTrade表只有上述4个字段。“trades=MtgoxTrade.objects.all()”只需要不到1秒的时间,但是for循环需要超过8秒!对“MtgoxTrade.objects.all().values('time'、'price'、'amount'、'type')”这种方式确实以20%的比率提高了性能!
return MtgoxTrade.objects.values('time', 'price', 'amount', 'type')