2

我在一个看起来像这样的表中有数据:

src_id, dst_id, params
int   , int   , array

我正在使用以下 Django 查询查询数据以从数组中提取一些值

dataset = query_set.values_list('src_id', 'dst_id', *[e.field for e in settings])

我需要像这样输出数据:

[
[1,2,[a,b,c,d]],
[3,4,[a,c,d,e]],
...
]

values_list返回一个元组列表,如 (1,2,a,b,c,d)(3,4,a,c,d,e)...

所以我一直在做以下事情来将元组值重新组合成一个数组:

[[d[0], d[1], d[2:]] for d in dataset]

它工作正常,但我有 1M+ 行,而且速度很慢。它也使用了大量的内存。理想情况下,我想在 SQL 中正确格式化数据(通过 Django)并将输出直接推送到 JSON 序列化程序,而无需生成中间数组。

有没有办法优化这段代码?

我研究过使用循环或 lambda,但这并没有太大的区别。我看着使用array,但它只需要原始类型,所以数组数组没有太多运气。

我正在寻找一种方法来查询数据库并以正确的格式直接输出数据,如果可能的话在 Django 中:

我看到 Django 可以像这样进行切片数组查找

dataset = query_set.values_list('src_id', 'dst_id', 'data__3_10')

例如,要获取索引 3 和 10 之间的值,但我需要检索特定索引(例如 1、4、5、6、8、11),而不是切片。

关于如何格式化这样的查询输出的任何提示?有可能,还是对 Django 来说太深奥了?我需要rawSQL 吗?

谢谢

4

2 回答 2

1

我能够直接在 Django 中格式化输出,而无需使用原始 SQL,使用以下extra()功能:

dataset = queryset.objects\
               .extra(select={'data': 'ARRAY[{}]'.format(",".join([fields])})\
               .values_list('src_id','dst_id','data')
return dataset.iterator()

这允许根据需要选择 SQL 数组中的特定索引。

返回迭代器(如@hynekcer 所建议),而不是结果数组本身,实际上更适合内存。

避免了重新格式化数据的循环,迭代器可以直接发送到 JSON 序列化器,该序列化器接受迭代器作为输入。

于 2017-10-17T17:37:57.197 回答
1

如果数据库是PostgreSQLOracle ,那么在Django 1.11中,通过应用于任何查询集(包括查询集)的 iterator() 方法可以着降低内存需求。然后默认使用服务器端游标,而不在 Django 或数据库驱动程序中进行任何缓存。阅读文档中的详细信息。values()values_list()

演示

qs = query_set.values_list('src_id', 'dst_id', 'data')
for row in qs.iterator():
    print(row) 

输出

(3, 4, ['a', 'c', 'd', 'e'])
...

完整示例

qs = query_set.values_list('src_id', 'dst_id', 'data')
with open(..., 'w') as f:
    f.write('[\n')
    for src_id, dst_id, data in qs.iterator():
        str_sub_array = ','.join(data[x] for x in column_settings)
        f.write('[{},{},[{}]],\n'.format(src_id, dst_id, str_sub_array)
    f.write(']\n')

内存需求可以忽略不计。

于 2017-10-15T21:36:29.300 回答