Mar*_*loJ 7 postgresql optimization execution-plan postgresql-9.3
我遇到了慢查询问题,这是由计划程序检查每个继承的表而不是仅具有约束的表引起的。
我有一个名为“search_result”的 0 行表。该表有几个继承的表,它们具有基于“极化”的不同约束,我们所有的数据都驻留在该表中。例如:
CREATE TABLE search_result_positive
(
CONSTRAINT search_result_positive_polarization_check CHECK (polarization = (1))
)
INHERITS (search_result);
CREATE TABLE search_result_negative
(
CONSTRAINT search_result_negative_polarization_check CHECK (polarization = (-1))
)
INHERITS (search_result);
CREATE TABLE search_result_unpolarized
(
CONSTRAINT search_result_unpolarized_polarization_check CHECK (polarization IS NULL)
)
INHERITS (search_result);
Run Code Online (Sandbox Code Playgroud)
例如,当我使用“WHEREpolarization = 1”执行查询时,查询规划器将显示它只检查了“search_result_positive”:表,这是所需的行为。
但是,当查询是“WHEREpolarization IS NULL”时,它会检查每个表,花费大量时间。以下是“search_result_positive”的示例:
SELECT "search_result".* FROM "search_result" WHERE (polarization = 1) ORDER BY published_on DESC LIMIT 20;
Limit (cost=0.44..17.65 rows=20 width=2027) (actual time=3.638..3.666 rows=20 loops=1)
-> Merge Append (cost=0.44..249453.67 rows=289872 width=2027) (actual time=3.637..3.663 rows=20 loops=1)
Sort Key: search_result.published_on DESC
-> Sort (cost=0.01..0.02 rows=1 width=2882) (actual time=0.004..0.004 rows=0 loops=1)
Sort Key: search_result.published_on DESC
Sort Method: quicksort Memory: 25kB
-> Seq Scan on search_result (cost=0.00..0.00 rows=1 width=2882) (actual time=0.002..0.002 rows=0 loops=1)
Filter: (polarization = 1)
-> Index Scan Backward using ix_search_result_positive_published_on_asc on search_result_positive (cost=0.42..245830.25 rows=289871 width=2027) (actual time=3.633..3.658 rows=20 loops=1)
Filter: (polarization = 1)
Planning time: 2.640 ms
Execution time: 3.762 ms
Run Code Online (Sandbox Code Playgroud)
现在,这就是我们查询 null 时发生的情况:
SELECT "search_result".* FROM "search_result" WHERE (polarization IS NULL) ORDER BY published_on DESC LIMIT 20;
Limit (cost=1.93..143.83 rows=20 width=1758) (actual time=205790.210..206266.419 rows=20 loops=1)
-> Merge Append (cost=1.93..462744.74 rows=65221 width=1758) (actual time=205790.208..206266.403 rows=20 loops=1)
Sort Key: search_result.published_on DESC
-> Sort (cost=0.01..0.02 rows=1 width=2882) (actual time=0.006..0.006 rows=0 loops=1)
Sort Key: search_result.published_on DESC
Sort Method: quicksort Memory: 25kB
-> Seq Scan on search_result (cost=0.00..0.00 rows=1 width=2882) (actual time=0.001..0.001 rows=0 loops=1)
Filter: (polarization IS NULL)
-> Index Scan using ix_search_result_hybrid_published_on_desc on search_result_hybrid (cost=0.14..44.44 rows=1 width=2882) (actual time=0.002..0.002 rows=0 loops=1)
Filter: (polarization IS NULL)
-> Index Scan Backward using ix_search_result_negative_published_on_asc on search_result_negative (cost=0.42..126163.49 rows=1 width=2039) (actual time=44646.431..44646.431 rows=0 loops=1)
Filter: (polarization IS NULL)
Rows Removed by Filter: 174428
-> Index Scan Backward using ix_search_result_neutral_published_on_asc on search_result_neutral (cost=0.42..53749.59 rows=1 width=1996) (actual time=29539.393..29539.393 rows=0 loops=1)
Filter: (polarization IS NULL)
Rows Removed by Filter: 115678
-> Index Scan using ix_search_result_no_apply_published_on_desc on search_result_no_apply (cost=0.14..44.44 rows=1 width=2882) (actual time=0.003..0.003 rows=0 loops=1)
Filter: (polarization IS NULL)
-> Index Scan Backward using ix_search_result_positive_published_on_asc on search_result_positive (cost=0.42..245105.57 rows=1 width=2027) (actual time=131590.509..131590.509 rows=0 loops=1)
Filter: (polarization IS NULL)
Rows Removed by Filter: 295475
-> Index Scan using ix_search_result_unpolarized_published_on_desc on search_result_unpolarized (cost=0.29..35643.06 rows=65215 width=1758) (actual time=13.863..490.048 rows=20 loops=1)
Filter: (polarization IS NULL)
Planning time: 1.197 ms
Execution time: 206266.593 ms
Run Code Online (Sandbox Code Playgroud)
这真让我抓狂。我不明白为什么每个表都被检查,而不仅仅是“search_result_unpolarized”。这已经让我发疯了。我对此唯一的其他选择是重写我们系统的一部分以仅查询特定表,而不是让 Postgres 决定,这将是相当多的工作。一定会有更好的办法。任何帮助或想法将不胜感激。
我们在 Amazon RDS 上使用 Postgres 9.3.19
约束排除有一些注意事项。这种情况(不考虑非 NULL 性,即使现有检查涉及它)并未在文档中列出,但在以后的版本中它仍然存在。解决方案是添加另一个显式排除 NULL 的检查:
ALTER TABLE search_result_positive ADD CHECK (polarization IS NOT NULL);
ALTER TABLE search_result_negative ADD CHECK (polarization IS NOT NULL);
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
118 次 |
最近记录: |