【发布时间】:2017-04-03 19:39:01
【问题描述】:
我有一个使用 Django 运行的自定义查询。如果我在 pgAdmin 中运行查询,响应时间是毫秒。但是,Django 中的相同查询大约需要 52 秒。
PgAdmin 输出:
EXPLAIN ANALYZE
select t.tag, t.detected_at, a.code as antenna_code, r.code as reader_code, s.slug
from tags_tag t
inner join sites_antenna a on (t.antenna_id = a.id)
inner join sites_reader r on (a.reader_id = r.id)
inner join sites_site s on (r.site_id = s.id)
where s.slug = 'BVC' and tag ~ '3E7'
order by t.detected_at DESC
limit 1
"Limit (cost=5.52..53.02 rows=1 width=37) (actual time=254.105..254.107 rows=1 loops=1)"
" -> Nested Loop (cost=5.52..87869.88 rows=1850 width=37) (actual time=254.101..254.101 rows=1 loops=1)"
" Join Filter: (a.id = t.antenna_id)"
" Rows Removed by Join Filter: 2210"
" -> Index Scan Backward using tags_tag_pkey on tags_tag t (cost=0.43..83561.74 rows=286729 width=31) (actual time=3.928..247.145 rows=369 loops=1)"
" Filter: ((tag)::text ~ '3E7'::text)"
" Rows Removed by Filter: 263"
" -> Materialize (cost=5.09..7.21 rows=1 width=14) (actual time=0.002..0.009 rows=6 loops=369)"
" -> Nested Loop (cost=5.09..7.21 rows=1 width=14) (actual time=0.179..0.237 rows=6 loops=1)"
" -> Hash Join (cost=4.95..6.44 rows=1 width=11) (actual time=0.165..0.195 rows=1 loops=1)"
" Hash Cond: (r.site_id = s.id)"
" -> Seq Scan on sites_reader r (cost=0.00..1.35 rows=35 width=11) (actual time=0.005..0.050 rows=35 loops=1)"
" -> Hash (cost=4.94..4.94 rows=1 width=8) (actual time=0.081..0.081 rows=1 loops=1)"
" Buckets: 1024 Batches: 1 Memory Usage: 9kB"
" -> Seq Scan on sites_site s (cost=0.00..4.94 rows=1 width=8) (actual time=0.043..0.074 rows=1 loops=1)"
" Filter: ((slug)::text = 'BVC'::text)"
" Rows Removed by Filter: 154"
" -> Index Scan using sites_antenna_reader_id_12e342c6_uniq on sites_antenna a (cost=0.14..0.71 rows=6 width=11) (actual time=0.007..0.019 rows=6 loops=1)"
" Index Cond: (reader_id = r.id)"
"Planning time: 28.225 ms"
"Execution time: 254.201 ms"
Django 输出 - print(connection.queries) 和 debug_toolbar:
{'time': '52.940', 'sql': "\n
select t.tag, t.detected_at, a.code as antenna_code, r.code as reader_code, s.slug \n
from tags_tag t\n
inner join sites_antenna a on (t.antenna_id = a.id)\n
inner join sites_reader r on (a.reader_id = r.id)\n
inner join sites_site s on (r.site_id = s.id)\n
where s.slug = 'BVC' and tag ~ '3E7.'\n
order by t.detected_at DESC\n
limit 1\n "}
此外,如果我通过模型运行它: tag_b = Tag.objects.filter(antenna__reader__site__slug='BVC', tag__startswith='3E7').order_by('-detected_at').first()
sql几乎一模一样,响应时间13秒左右(还是太慢了)。
{'time': '13.201', 'sql':
'SELECT "tags_tag"."id", "tags_tag"."antenna_id", "tags_tag"."detected_at", "tags_tag"."tag", "tags_tag"."created_at", "tags_tag"."updated_at"
FROM "tags_tag"
INNER JOIN "sites_antenna" ON ("tags_tag"."antenna_id" = "sites_antenna"."id")
INNER JOIN "sites_reader" ON ("sites_antenna"."reader_id" = "sites_reader"."id")
INNER JOIN "sites_site" ON ("sites_reader"."site_id" = "sites_site"."id")
WHERE ("sites_site"."slug" = \'BVC\' AND "tags_tag"."tag"::text LIKE \'3E7%\')
ORDER BY "tags_tag"."detected_at"
DESC LIMIT 1'}
注意:我正在执行自定义 sql,因为我正在计数,所以我可以使用一个查询来获取总数。即使在 SQL 中使用 count over,pgadmin 和 Django 的响应时间也几乎相同。
select t.tag, t.detected_at, a.code as antenna_code, r.code as reader_code, s.slug, count(*) over () as total_tags
...
有什么想法/建议可以在 Django 中加快速度吗?
【问题讨论】:
-
我可以建议的一件事是尝试向表中添加更多索引。也许
t.detected_at,s.slug,r.code。
标签: django postgresql