Postgres的。查询有时会很长。

时间:2015-12-01 14:52:22

标签: database postgresql

我需要帮助或任何提示。我有Postgres DB 9.4并且有一个查询处理得很慢很多。

SELECT COUNT(*) FROM "table_a" INNER JOIN "table_b" ON "table_b"."id" = "table_a"."table_b_id" AND "table_b"."deleted_at" IS NULL WHERE "table_a"."deleted_at" IS NULL AND "table_b"."company_id" = ? AND "table_a"."company_id" = ?

查询计划 -

Aggregate (cost=308160.70..308160.71 rows=1 width=0)
             -> Hash Join (cost=284954.16..308160.65 rows=20 width=0)
                                    Hash Cond: ?
    -> Bitmap Heap Scan on table_a (cost=276092.39..299260.96 rows=6035 width=4)
                                    Recheck Cond: ?
                                                Filter: ?
-> Bitmap Index Scan on index_table_a_on_created_at_and_company_id (cost=0.00..276090.89 rows=6751 width=0)
                                         Index Cond: ?
            -> Hash (cost=8821.52..8821.52 rows=3220 width=4)
        -> Bitmap Heap Scan on table_b (cost=106.04..8821.52 rows=3220 width=4)
                                Recheck Cond: ?
                                                Filter: ?
    -> Bitmap Index Scan on index_ table_b_on_company_id (cost=0.00..105.23 rows=3308 width=0)
                                        Index Cond: ? 

但通常,这是执行足够快的查询(大约69.7ms)。我不明白为什么有时会发生这种情况。我在这个时期的性能日志中看到,我的RDS实例消耗了大量内存并计算此查询大约每秒100次。所以伙计们,请帮忙,我在哪里解决这个问题。

1 个答案:

答案 0 :(得分:-1)

我不确定这是否能解决您的问题:)

  • 当此查询返回非常快的结果时,它返回缓存中的结果,而不是再次执行查询,而不是在那时准备结果。

  • 首先,您必须检查这些表上是否执行了太多查询,尤其是插入/更新/删除。此类查询导致锁定,选择必须等到锁定被释放。

  • 查询可能会很慢,因为joinwhere之间的table_atable_b子句的比较成本太高。

  • 您可以将indexes应用于"table_b"."id", "table_a"."table_b_id", "table_a"."deleted_at", "table_b"."company_id", AND "table_a"."company_id"列来降低费用。

  • 您可以创建view以降低成本。视图返回缓存的信息。

  • 最后一件事是你也可以通过使用临时表来降低成本。我在下面给出了一个例子。

<强> QUERIES:

CREATE TEMPORARY TABLE table_a_temp as 
SELECT "table_a"."table_b_id" FROM "table_a" 
WHERE "table_a"."deleted_at" IS NULL AND "table_a"."company_id" = ? ;

CREATE TEMPORARY TABLE table_b_temp as 
SELECT "table_b"."id" FROM "table_a" 
WHERE"table_b"."deleted_at" IS NULL AND "table_b"."company_id" = ?;

SELECT COUNT(*) FROM "table_a_temp" INNER JOIN "table_b_temp" 
ON "table_b_temp"."id" = "table_a_temp"."table_b_id" ;