postgresql - PostgreSQL default_statistics_target 没有改进行估计
问题描述
我正在尝试优化我们对 Postgres 的查询,这有时需要几分钟才能使用巨大的表。开始查看查询计划,并注意到使用EXPLAIN ANALYZE
.
这将我引向default_statistics_target
控制命令采样的行数ANALYZE
以收集查询计划器使用的统计信息的参数。正如少数博客所建议的那样,我尝试通过增加值将其设置为1000
并将事件设置为最大允许值10000
.
每次ANALYZE
运行以确保其统计信息已更新。但令人惊讶的是,这根本没有改善行估计。事实上,它进一步降低了估计值,这似乎很奇怪。
还通过将值减小到 进行测试10
。这似乎使计数有所改善。所以我很困惑,如果参数真的做了我认为它做的事情。或者,如果有其他方法可以改进行估计。任何帮助将非常感激。
Postgres 版本:9.6
查询计划:在最后的索引扫描步骤中,估计为 462,但实际为 1.9M。 https://explain.depesz.com/s/GZY
更改后default_statistics_target = 1000
,索引扫描步骤中的行是
-> (cost=0.57..120.42 rows=114 width=32) (actual time=248.999..157947.395 rows=1930518 loops=1)
并将其设置为default_statistics_target = 10
,计数为:
-> (cost=0.57..2610.79 rows=2527 width=32) (actual time=390.437..62668.837 rows=1930518 loops=1)
正在考虑的 PS 表有超过 100M 行。
解决方案
这看起来像一个相关性问题。规划器假设 project_id、event_name_id 和“timestamp”的条件是独立的,因此会乘以它们的估计选择性。如果它们不是独立的,那么再多的传统统计数据也无济于事。也许您需要扩展统计信息
此外,在制定计划时,它甚至不知道 event_name_id 将与哪个值进行比较,因为 $0 直到运行时才确定,因此它不能为此使用特定于值的统计信息。您可以手动执行子查询,然后将结果值硬编码到查询中的该位置,因此规划器在规划时知道该值是什么。
推荐阅读
- python - 永远在线程内运行 Python 3 asyncio.coroutine
- python - 在 python 中表示金钱而不损失价值的最佳实践
- java - 对这行 Java 代码如何按降序排序感到困惑
- mongodb - 如何在 UpdateOne 语句中做“省略”
- laravel - 如何在 laravel 5.8 中创建 3 级用户?
- postgresql - 在家庭网络外访问 Raspberry pi 上的数据库的安全方式
- c# - 如何检查资产文件是 YAML 还是二进制格式?我是直接切换它的格式吗?
- javascript - 如何在 Rails / HTML 中打印页面?
- python - Python - 替换模块中的特定文件
- javascript - 修改 ImageData 时画布看起来被拉伸