【问题标题】:Django custom query extremely slowDjango 自定义查询极慢
【发布时间】: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_ats.slugr.code

标签: django postgresql


【解决方案1】:

因为我是个白痴……

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

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

编辑:使用选项“use_remote_estimate”来加快对链接表的查询。前任。

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

【讨论】:

    猜你喜欢
    • 2019-10-25
    • 1970-01-01
    • 1970-01-01
    • 2012-05-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-26
    相关资源
    最近更新 更多