Django自定义查询极其缓慢

时间:2017-04-03 19:39:02

标签: django postgresql

我有一个自定义查询我正在使用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,因为我正在进行计数,因此我可以使用一个查询来获取总数。即使使用count over,在SQL中,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的速度吗?

1 个答案:

答案 0 :(得分:0)

因为我是个白痴......

Django中使用的查询很慢,因为它实际上是从链接表(Foreign Data Wrapper)查询数据。我可以使用链接表直接在数据库上复制运行查询的结果。

需要弄清楚如何加快postgresql中链接表的连接速度。

编辑:使用选项" use_remote_estimate"加快链接表的查询速度。防爆。

ALTER SERVER <servername> OPTIONS (add use_remote_estimate 'true')