几乎相同的 PostgreSQL 查询相差 1 分钟?

Posted

技术标签:

【中文标题】几乎相同的 PostgreSQL 查询相差 1 分钟?【英文标题】:1 minute difference in almost identical PostgreSQL queries? 【发布时间】:2016-07-28 08:37:44 【问题描述】:

我的 Rails 应用程序能够按 state_code 过滤记录。我注意到,当我将“CA”作为搜索词传递时,我几乎可以立即得到结果。例如,如果我将通过“AZ”,则需要一分钟以上。

我不知道为什么会这样?

以下是来自 psql 的查询说明: 快一:

 EXPLAIN ANALYZE SELECT
   accounts.id
 FROM "accounts"
 LEFT OUTER JOIN "addresses"
   ON "addresses"."addressable_id" = "accounts"."id"
   AND "addresses"."address_type" = 'mailing'
   AND "addresses"."addressable_type" = 'Account'
 WHERE "accounts"."organization_id" = 16
 AND (addresses.state_code IN ('CA'))
 ORDER BY accounts.name DESC;
                                                                       QUERY PLAN
---------------------------------------------------------------------------------------------------------------------------------------------------------
 Sort  (cost=4941.94..4941.94 rows=1 width=18) (actual time=74.810..74.969 rows=821 loops=1)
   Sort Key: accounts.name
   Sort Method: quicksort  Memory: 75kB
   ->  Hash Join  (cost=4.46..4941.93 rows=1 width=18) (actual time=70.044..73.148 rows=821 loops=1)
         Hash Cond: (addresses.addressable_id = accounts.id)
         ->  Seq Scan on addresses  (cost=0.00..4911.93 rows=6806 width=4) (actual time=0.027..65.547 rows=15244 loops=1)
               Filter: (((address_type)::text = 'mailing'::text) AND ((addressable_type)::text = 'Account'::text) AND ((state_code)::text = 'CA'::text))
               Rows Removed by Filter: 129688
         ->  Hash  (cost=4.45..4.45 rows=1 width=18) (actual time=2.037..2.037 rows=1775 loops=1)
               Buckets: 1024  Batches: 1  Memory Usage: 87kB
               ->  Index Scan using organization_id_index on accounts  (cost=0.29..4.45 rows=1 width=18) (actual time=0.018..1.318 rows=1775 loops=1)
                     Index Cond: (organization_id = 16)
 Planning time: 0.565 ms
 Execution time: 75.224 ms
(14 rows)

慢一:

EXPLAIN ANALYZE SELECT
  accounts.id
FROM "accounts"
LEFT OUTER JOIN "addresses"
  ON "addresses"."addressable_id" = "accounts"."id"
  AND "addresses"."address_type" = 'mailing'
  AND "addresses"."addressable_type" = 'Account'
WHERE "accounts"."organization_id" = 16
AND (addresses.state_code IN ('NV'))
ORDER BY accounts.name DESC;
                                                                       QUERY PLAN
---------------------------------------------------------------------------------------------------------------------------------------------------------
 Sort  (cost=4917.27..4917.27 rows=1 width=18) (actual time=97091.270..97091.277 rows=25 loops=1)
   Sort Key: accounts.name
   Sort Method: quicksort  Memory: 26kB
   ->  Nested Loop  (cost=0.29..4917.26 rows=1 width=18) (actual time=844.250..97091.083 rows=25 loops=1)
         Join Filter: (accounts.id = addresses.addressable_id)
         Rows Removed by Join Filter: 915875
         ->  Index Scan using organization_id_index on accounts  (cost=0.29..4.45 rows=1 width=18) (actual time=0.017..10.315 rows=1775 loops=1)
               Index Cond: (organization_id = 16)
         ->  Seq Scan on addresses  (cost=0.00..4911.93 rows=70 width=4) (actual time=0.110..54.521 rows=516 loops=1775)
               Filter: (((address_type)::text = 'mailing'::text) AND ((addressable_type)::text = 'Account'::text) AND ((state_code)::text = 'NV'::text))
               Rows Removed by Filter: 144416
 Planning time: 0.308 ms
 Execution time: 97091.325 ms
(13 rows)

慢的结果是25行,快的结果是821行,更加混乱。

【问题讨论】:

有多少行以“C”开头,多少行以“A”开头?您也可以向我们展示您的查询吗? @LajosArpad 编辑了我的问题。我的“C”记录多于“A”记录。不仅“AZ”的列表要大得多,而且几乎只有“CA”才能正常工作,这对我来说很奇怪。 Petya,这很有趣。人们会期望对加利福尼亚的搜索比对亚利桑那的搜索要慢。然而,这里的事情正在以不同的方式发生。我们可以排除 order by 作为原因,因为在这两种情况下结果的数量几乎相同。我想知道选择子句是否使它变慢。您可以在两种情况下都选择一个小列进行测试吗?如果这样做,行为会改变吗? @LajosArpad 对吧?刚刚从查询中删除了大部分,只留下了真正重要的东西,这次我还使用 NV 来进行慢速查询而不是 AZ,以表明它不仅仅是 AZ。 @LajosArpad 你知道为什么在使用慢请求嵌套循环的解释中,而在快速请求中它被 HASH JOIN 取代吗?我认为这就是原因,我只是不知道它来自哪里 【参考方案1】:

我通过使用 psql 命令行中的VACUUM ANALYZE 命令解决了这个问题。

【讨论】:

以上是关于几乎相同的 PostgreSQL 查询相差 1 分钟?的主要内容,如果未能解决你的问题,请参考以下文章

两个字符串几乎相等

PostgreSQL递归查询

postgresql 查询多个相同的表

求个sqlserver查询语句

Postgresql 函数执行的时间比相同的查询长得多

需要查询以列出两列相对相同的行,但需要注意 Postgresql