几乎相同的 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 分钟?的主要内容,如果未能解决你的问题,请参考以下文章