Django在分区表上的保存和更新速度变慢,但查询速度更快

时间:2018-12-07 17:56:29

标签: django postgresql database-partitioning postgresql-10

我在Postgres9和Postgres10中有相同的表,除了Postgres10表是按状态划分的。两个表中都有大约8000万条记录

当我这样查询时,在分区表上它的速度比在Postgres9未分区表上快10倍。万岁!

# This is fast with a partition, and slow without
parcels = Parcel.objects.filter(state='15', boundary__intersects=polygon)

但是,当我尝试通过Django进行更新时,分区表上的速度大约慢了1000倍(大约需要2分钟),而它是Postgres9版本上的:

for parcel in parcels:
    do something
    # This is slow with a partition, and fast without
    parcel.save()

但是当我直接通过psql进行更新时,它在Postgres10中的分区表上非常快,而在Postgres9中的未分区表上则非常慢:

# This is fast with a partition, and slow without
UPDATE parcel SET field=42 WHERE state='15' AND parcel_id='someid';

为什么我在Django中对save的调用比直接通过psql更新要慢得多? QuerySet.explain()操作是否与save等效?

1 个答案:

答案 0 :(得分:0)

Postgres10比Postgres9慢的原因是分区表不允许在父表上使用主键。因此,我对parcel.save()的调用试图运行类似UPDATE parcel SET field=42 WHERE "id" = 'someid';的查询,但是在分区表上按id查询非常慢。

我通过向每个子表添加主键来解决此问题。例如。 ALTER TABLE parcel_01 ADD PRIMARY KEY (id);。当我为每个孩子添加它时,它具有相似的效果,并且我的更新时间减少了99.9%。总体而言,在Postgres10中使用分区表可将我正在使用的工具的总运行时间减少75%(从40分钟减少到大约10分钟)

我要感谢@ 2ps建议我查看生成的SQL,并建议一种无需使用主键即可强制执行我想要的查询的方法。