postgresql - Django 查询比相同的Postgres查询慢 40倍?

  显示原文与译文双语对照的内容
0 0

我正在运行 Postgres 9.3的Django 1.7,运行 runserver 。 数据库中有 200m 行或者大约 80GB 行数据。 我正在尝试调试Postgres中相同的查询速度,但 Django 中速度较慢。

数据结构如下所示:

class Chemical(models.Model):
 code = models.CharField(max_length=9, primary_key=True)
 name = models.CharField(max_length=200)
class Prescription(models.Models):
 chemical = models.ForeignKey(Chemical)
. . . other fields

数据库是用C 排序规则和适当的索引建立的:

 Table"public.frontend_prescription"
 Column | Type | Modifiers
 id | integer | not null default nextval('frontend_prescription_id_seq'::regclass)
 chemical_id | character varying(9) | not null
 Indexes:
"frontend_prescription_pkey" PRIMARY KEY, btree (id)
"frontend_prescription_a69d813a" btree (chemical_id)
"frontend_prescription_chemical_id_4619f68f65c49a8_like" btree (chemical_id varchar_pattern_ops)

这是我的观点:

def chemical(request, bnf_code):
 c = get_object_or_404(Chemical, bnf_code=bnf_code)
 num_prescriptions = Prescription.objects.filter(chemical=c).count()
 context = {
 'num_prescriptions': num_prescriptions
 }
 return render(request, 'chemical.html', context)

瓶颈是 .count() 。 调用 Django 调试工具栏显示在这是 2647ms ("时间"标题下方) 所花费的时间,但解释部分建议时间应该为 621ms ( 在底部):

screenshot of debug toolbar

即使是陌生人,如果我直接在Postgres中运行同一个查询,它似乎只需要 200 -300ms:

# explain analyze select count(*) from frontend_prescription where chemical_id='0212000AA';
QUERY PLAN
-------------------------------------------------------------------------------------------------------------------------------------------------------------
 Aggregate (cost=279495.79..279495.80 rows=1 width=0) (actual time=296.318..296.318 rows=1 loops=1)
 -> Bitmap Heap Scan on frontend_prescription (cost=2104.44..279295.83 rows=79983 width=0) (actual time=162.872..276.439 rows=302389 loops=1)
 Recheck Cond: ((chemical_id)::text = '0212000AA'::text)
 -> Bitmap Index Scan on frontend_prescription_a69d813a (cost=0.00..2084.44 rows=79983 width=0) (actual time=126.235..126.235 rows=322252 loops=1)
 Index Cond: ((chemical_id)::text = '0212000AA'::text)
 Total runtime: 296.591 ms 

所以我的问题是:在调试工具栏中,解释语句与 Django 中的实际性能不同。 它比Postgres中的原始查询还慢。

为什么有这种差异? 如何调试/提高 Django 应用程序的性能?

更新:下面是另一个随机示例: 350ms 要解释,要渲染超过 10,000 ! 帮助,这使得我的Django 应用几乎无法使用。

enter image description here

更新 2: 这是另一个慢( 40秒在 Django 中,600ms 在解释。) 查询的分析面板。 如果我正在读它,它建议从我的视图中每个SQL调用都是 13秒。 这是不是瓶颈?

enter image description here

奇怪的是,配置的调用只对返回大量结果的查询慢,所以我不认为延迟是应用于每个调用的Django 连接开销。

更新 3: 我尝试在原始SQL中重写视图,而性能现在更好一些,尽管我仍然看到了大约一半时间的查询。 ( 我必须在每次创建游标时创建并创建游标,否则我将获得 InterfaceError 和关于游标死的消息,不确定是否对调试有用。 我已经设置了 CONN_MAX_AGE=1200 ) 无论如何,这很容易执行,但它很容易受到注入等的影响:

cursor = connection.cursor()
query ="SELECT * from frontend_chemical WHERE code='%s'" % code
c = cursor.execute(query)
c = cursor.fetchone()
cursor.close()
cursor = connection.cursor()
query ="SELECT count(*) FROM frontend_prescription WHERE chemical_id="
query +="'" + code +"';"
cursor.execute(query)
num_prescriptions = cursor.fetchone()[0]
cursor.close()
context = {
 'chemical': c,
 'num_prescriptions': num_prescriptions
}
return render(request, 'chemical.html', context)
时间:原作者:6个回答

0 0

当 Django 运行查询时很可能需要从磁盘读取数据。 但是,当你检查查询为什么慢时,数据已经在内存中,因为前面的查询。

最简单的解决方案是购买更多的内存或者更快的io系统。

原作者:
...