慢Postgres JOIN查询

时间:2010-09-17 19:31:48

标签: django postgresql

我正在尝试优化由Django ORM生成的慢查询。这是一个多对多查询。运行需要1分钟以上。

这些表有大量数据,但它们并不大(sp_article中有400k行,sp_article_categories中有300k行)

#categories.article_set.filter(post_count__lte=50)

EXPLAIN ANALYZE SELECT * 
                  FROM "sp_article" 
            INNER JOIN "sp_article_categories" ON ("sp_article"."id" = "sp_article_categories"."article_id") 
                WHERE ("sp_article_categories"."category_id" = 1081  
                  AND "sp_article"."post_count" <= 50 )

Nested Loop  (cost=0.00..6029.01 rows=656 width=741) (actual time=0.472..25.724 rows=1266 loops=1)
  ->  Index Scan using sp_article_categories_category_id on sp_article_categories  (cost=0.00..848.82 rows=656 width=12) (actual time=0.015..1.305 rows=1408 loops=1)
        Index Cond: (category_id = 1081)
  ->  Index Scan using sp_article_pkey on sp_article  (cost=0.00..7.88 rows=1 width=729) (actual time=0.014..0.015 rows=1 loops=1408)
        Index Cond: (sp_article.id = sp_article_categories.article_id)
        Filter: (sp_article.post_count <= 50)
Total runtime: 26.536 ms

我有一个索引:

sp_article_categories.article_id (type: btree)
sp_article_categories.category_id
sp_article.post_count (type: btree)

有关如何调整此内容以快速获取查询的任何建议吗?

谢谢!

5 个答案:

答案 0 :(得分:1)

您在此提供了重要信息 - 解释分析。虽然没有显示1秒的运行时间,但它显示的是20毫秒。所以 - 这不是正在运行的查询,或者问题出在其他地方。

解释分析和实际应用之间的唯一区别是实际上没有返回结果。你需要大量数据才能将速度减慢到1秒。

其他建议都不合适,因为他们忽略了查询不慢的事实。你有相关的索引(连接的两边都使用了索引扫描),并且规划器完全能够首先对类别表进行过滤(这就是拥有一半体面的查询规划器的全部意义)。

所以 - 你首先需要弄清楚究竟什么是慢......

答案 1 :(得分:0)

sp_article_categories.category_id

上添加索引

答案 2 :(得分:0)

从纯SQL角度来看,如果基表中的行数较少,则连接会更有效,并且在该表连接到另一个表之前会对该表执行WHERE条件。

那么看看你是否可以让Django先从类别中选择,然后在加入文章表之前过滤category_id。

伪代码如下:

SELECT * FROM categories c
INNER JOIN articles a
    ON c.category_id = 1081
    AND c.category_id = a.category_id

像史蒂文建议的那样在category_id上加上一个索引。

答案 3 :(得分:0)

您也可以使用字段名称*。

从......中选择[字段]

答案 4 :(得分:0)

我假设您已对数据库运行分析以获取新的统计信息。

似乎sp_article.id和sp_article_categories.article_id之间的连接成本很高。什么数据类型是文章ID,数字?如果不是,你应该考虑将它变成数字 - 整数或bigint,无论你需要什么套件。根据我的经验,它可以在性能上产生很大的不同。希望它有所帮助。

干杯! //约翰