我运行 Django 1.7 和 Postgres 9.3,运行runserver
. 我的数据库中有大约 2 亿行或大约 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 调试工具栏显示在此花费的时间是 2647 毫秒(在下面的“时间”标题下),但解释部分建议花费的时间应该是 621 毫秒(在底部):
更奇怪的是,如果我直接在 Postgres 中运行相同的查询,它似乎只需要 200-300 毫秒:
# 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
所以我的问题是:在调试工具栏中,EXPLAIN 语句与 Django 中的实际性能不同。而且它仍然比 Postgres 中的原始查询慢。
为什么会出现这种差异?我应该如何调试这个/提高我的 Django 应用程序的性能?
更新:这是另一个随机示例:解释 350 毫秒,渲染超过 10,000 毫秒!帮助,这使我的 Django 应用程序几乎无法使用。
更新 2:这是另一个慢速(Django 中为 40 秒,EXPLAIN 中为 600 毫秒)查询的 Profiling 面板。如果我没看错,这表明我认为每个 SQL 调用都需要 13 秒……这是瓶颈吗?
奇怪的是,分析调用仅对于返回大量结果的查询很慢,所以我不认为延迟是适用于每个调用的一些 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)