问题标签 [query-planner]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
postgresql - 对大型空间选择进行排序不使用 GiST 索引(Postgres 11.5)
我有一个表 ( demo
),其中一个序列作为其主键 ( seqno
) 和一个geometry
包含在 JSONB 列 ( doc
) 中的属性。我为序列列配置了一个主键约束,为几何配置了一个 GiST 索引。我已经通过运行收集了统计数据VACUUM ANALYZE
。这是一个相当大的表(42M 行)。
我想在相当大的区域上执行空间过滤器并返回前 10 行,按其主键排序。因此,我尝试了以下查询:
这会产生以下查询计划:
这说明使用主键约束索引扫描所有行并对每一行进行空间过滤,这显然是非常低效的。给定的空间谓词有超过 5M 的匹配。根本不使用 GiST 索引。
但是,当省略 ORDER BY 子句时,几何属性的 GiST 索引会被正确使用,这样效率更高。
有没有办法让这个查询快速?我们可以让查询规划器将 GiST 索引与 PK 索引结合起来得到一个排序的结果吗?还有其他建议吗?
sql - 类似查询中的查询规划器差异
我有两张表,一张用于个人资料,一张用于个人资料的就业状况。这两个表具有一对一的关系。一份个人资料可能没有工作状态。表模式如下(为清楚起见,删除了不相关的列):
使用这些表格,我被要求列出所有失业的个人资料。失业档案被定义为没有就业记录或就业状态不是“已批准”的档案。
我的第一个尝试是以下查询:
这里的假设是所有配置文件都将与他们各自的工作一起列出,然后我可以使用 where 条件过滤它们。任何没有就业记录的个人资料都将具有就业状态,null
因此会被条件过滤。但是,此查询不会返回没有工作的个人资料。
经过一番研究,我发现了这篇文章,解释了为什么它不起作用并转换了我的查询:
实际上确实有效。但是,我的 ORM 产生了一个稍微不同的查询,但它不起作用。
唯一的区别是 select 子句。我试图理解为什么这种细微的差异会产生如此大的差异,然后对所有三个查询进行了解释分析:
第一个和第二个查询计划几乎相同,一个是哈希连接,另一个是右哈希连接,而最后一个查询甚至不做连接或 where 条件。
我想出了一个确实有效的第四个查询:
我对这个主题的问题是:
- 为什么第二个和第三个查询的查询计划不同,即使它们具有相同的结构?
- 为什么查询计划第一个和第四个查询不同,即使它们的结构相同?
- 为什么 Postgres 完全忽略我的连接以及第三个查询的条件?
编辑:
对于以下示例数据,预期的查询应返回 2 和 3。
postgresql - PostgreSQL 12.4 查询计划器忽略子分区约束,导致表扫描
我有一张桌子
由每个分区并由每个A
子分区B
(即,每个分区都有一个值)。A
基数 <10 且B
基数 <100。T
有大约 60 亿行。
当我运行查询
它修剪顶级分区(那些 where A != 1
),但对所有子分区执行表扫描以找到B
. 我以为它会知道,基于分区设计,它只需要检查分区约束来确定B
给定的可能值A
,但可惜,事实并非如此。
A
or上没有索引B
,但每个分区上都有一个主键(C,D)
,这似乎无关紧要,但我想我应该提一下。我也有一个 BRIN 索引C
。知道为什么 Postgres 查询计划器不咨询子分区约束以避免表扫描吗?
postgresql - Postgresql,每次更新索引或结构后手动使用分析 $table_name 来更新查询计划器?真的吗?
我已经尝试了两天的查询和索引以找到最快的解决方案,直到今天我才发现感谢这个答案,使用“ analyze $table_name;
”命令EXPLAIN
然后查询在添加或删除索引后完全更改。
我的工作包括:
- 使用 Potgresql 13
- 使用与生产数据库尽可能相似的数据库,无论是在数据类型还是数量方面
- 编写将由后端语言生成和使用的查询
- 尝试各种索引(同时我也在学习 Postgresql)
- 添加一个索引并尝试 EXPLAIN
Sequential Scan
尽管有新索引,我仍然看到- 所以由于没有使用索引,我继续更好地理解并找到另一个解决方案
- 除了今天,我意识到使用“
analyze $table_name;
”来更新 Postgresql 查询计划就足够了
问题
这是我必须做的事情吗?
我可以自动设置它,以便在每次修改索引或正在开发的结构后自动分析它吗?
此分析是否在生产中自动执行?
postgresql - 当 Inner Select Index Cond 更快时,Postgres 使用 Hash Join 和 Seq Scan
tracking
当索引可用时,Postgres 对表使用更重的 Seq Scan 。第一个查询是原始尝试,它使用 Seq Scan,因此查询速度很慢。我尝试使用内部选择强制执行索引扫描,但 postgres 将其转换回具有几乎相同运行时的有效相同查询。我终于从查询二的内部选择中复制了列表来进行第三个查询。最后,postgres 使用了索引扫描,这大大减少了运行时间。第三个查询在生产环境中不可行。什么会导致 postgres 使用最后一个查询计划?
(两张桌子都使用了真空)
表
- 跟踪(worker_id,localdatetime)总记录:118664105
- project_worker(id, project_id)总记录:12935
指数
- CREATE INDEX tracking_worker_id_localdatetime_idx ON public.tracking USING btree (worker_id, localdatetime)
查询
SELECT worker_id, localdatetime FROM tracking t JOIN project_worker pw ON t.worker_id = pw.id WHERE project_id = 68475018
SELECT worker_id, localdatetime FROM tracking t WHERE worker_id IN (SELECT id FROM project_worker WHERE project_id = 68475018 LIMIT 500)
SELECT worker_id, localdatetime FROM tracking t WHERE worker_id IN (322016383,316007840,...,285702579)
... 代替查询中使用的 500 个 id 条目
相同的查询在另一组 500 个 id 上运行
sql - Postgres 中的查询读取了多少磁盘页面?
我想知道在运行单个 Postgres 查询时从磁盘(而不是从缓存中)读取了多少页(表 + 索引,如果有的话)。更好的是,如果有任何方法可以从 EXPLAIN ANALYZE 中提取此信息。
sql-server - 第一次运行每晚重新编译的存储过程非常慢,然后快得多
我们有一个夜间作业,在遗留数据库中运行一个复杂的存储过程。存储过程使用不同的参数运行四次。在增加服务器上的 CPU 和内存之前,第一次运行通常会在 30 秒后超时(当前默认超时),随后的运行会执行得更快。
OPTION (RECOMPILE) 是在存储过程中的查询上设置的,我怀疑执行计划的重新编译可能是罪魁祸首。但是,如果仅归结为执行计划的编译,大概这会对作业中对存储过程的每次调用产生类似的影响,而不仅仅是第一次调用。
难道是在创建第一个执行计划时必须重新构建一些昂贵的依赖统计信息,并且这些统计信息被重复用于后续的重新编译?
如果是这种情况,我将如何诊断?此外,除了增加第一次通话的超时时间之外,有没有办法解决这个问题?
indexing - PostgreSQL:多列索引(jsonb,整数)部分与@>和=条件一起使用
设置
具有一jsonb
列attributes
和非唯一数字 ID的表campaignid
:
该表将有多达 500M 行、任意键/值attributes
和数百个不同的campaignid
值。
表上存在两个索引:
我做了什么
我执行了查询:
预期成绩
我希望索引被充分campaignid_attrs_idx
使用(campaignid,attributes)
并且查询能够很快完成。
实际结果
该查询需要很长时间(约 40 秒)才能执行。
这是来自的输出explain (ANALYZE, COSTS)
:
结论
似乎索引campaignid_attrs_idx
用于attributes @> '{"CountryId": 3}'
返回约 80M 行的查询的第一部分,而该索引用于并行返回约 3M 行的子句campaignid_idx
的第二部分。将两个部分的结果相交以得出满足这两个条件的集合。然后是位图堆扫描,验证结果集符合所需条件,大部分时间(16893.439..39549.891)WHERE
campaignid = 97
我的主要问题是,为什么不campaignid_attrs_idx
用于过滤这两个条件?
编辑:我删除了第二个索引campaignid_attrs_idx
以查看多列索引是否将用于这两个条件。奇怪的是我仍然看到索引扫描中使用的唯一条件之一。这是计划:
sql - 为什么在 Postgres 中的 RAM 和磁盘中排序时我的查询速度较慢?
我使用 AWS RDS PG 12.5(db.t3.xlarge / 4vCPUs / 16GB RAM / SSD 存储)。
我试图通过调整work_mem
参数来优化查询,以避免在磁盘上溢出数据以对数据进行排序。
正如预期的那样,当增加work_mem
from 4MB
to时100MB
,使用快速排序而不是外部合并磁盘。
但是,总执行时间更长(2293ms
vs 2541ms
)。
- 为什么快速排序没有显着的收益?我认为 RAM 优于磁盘排序。(
540ms
外部合并磁盘与527ms
快速排序) - 为什么 seqscans、hash 和 merge 操作更慢?(为什么
work_mem
会影响这些操作?)
我发现了这个类似的 SO 帖子,但他们的问题是他们的排序只是整个执行时间的一小部分。
任何见解都会受到欢迎。
查询:
work_mem=4MB 的查询计划(链接到 depesz):
work_mem=100MB 的查询计划(链接到 depesz):
postgresql - PostgreSQL 升级到 12+ 将哈希连接更改为慢速嵌套循环
我们正在尝试从版本 9 系列升级,并有一个破坏交易的慢查询,它在 10 和 11 中运行良好,但在 12 和 13 中慢很多倍。我已经测试了 11 和 12 系列中的次要版本, 次要版本不影响它。
问题在于规划器选择嵌套循环连接而不是它应该使用的哈希连接。
v11 哈希连接:
v12 嵌套循环:
我们测试环境中的升级过程是使用 pg_upgrade 完成的,并在测试此查询之前进行全面分析。
那么12有什么变化呢?