问题标签 [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.

0 投票
1 回答
122 浏览

indexing - SQLite R*Tree 索引不与 DISTINCT 一起使用

在 SQLite 3.20.1 中,我创建了一个 R*Tree 索引 ( dog_bounds) 和一个临时表 ( frisbees),如下所示:

使用此索引进行查询很快,如下所示:

但是,如果我 select DISTINCT(dog_id),则不再使用索引,并且查询会变慢,即使在以下情况下也是如此ANALYZE

我怎样才能获得这里使用的 R*Tree 索引?复制狗将是一种耻辱!

0 投票
1 回答
127 浏览

mysql - 连接时的 MySQL 索引使用情况

我知道有几个与此类似的问题,但我发现的问题与我的问题没有直接关系。

一些初始上下文:我有一个名为 ft_booking 的事实表,其中包含大约 10MM 条记录。我有一个名为 dm_date 的维度,有大约 11k 条记录,即日期。像往常一样,这些表通过外键关联。ft_booking 表中有 3 个日期外键,一个用于登机,一个用于预订,一个用于取消。所有列的定义都非常相同,并且每个列的不同记录的数量相似(每列中的不同值从 2.5k 到 3k 不等)。

我去:

在此处输入图像描述

如您所见,在预订表中使用了索引,并且查询运行得非常快,即使在我的过滤器中,我使用的是 date() 函数。为简洁起见,我将声明使用列 fk_date_boarding 也会发生同样的情况。但是,看看这个:

在此处输入图像描述

出于某种神秘的原因,计划者选择不使用索引。现在,我知道在列上使用某些函数会强制数据库执行全表扫描,以便能够在列上应用该函数,从而绕过索引。但是,在这种情况下,该函数不在实际的外键列上,这是在预订表中进行查找的地方。

如果我删除 date() 函数,则索引将按预期用于任何这些列。有人可能会说,“好吧,你为什么不干脆去掉 date() 函数呢?” - 我使用元数据库,一个允许用户使用图形界面来构建查询而不了解 MySQL 的界面,该工具的当前限制之一是它在构建不直接写入的查询时总是使用 date() 函数MySQL - 因此,我无法删除正在运行的查询中的函数。

实际问题:为什么 MySQL 在前两种情况下使用索引,但在后一种情况下不使用,考虑到所有列的不同值的数量几乎相同,并且它们具有确切的 smae 定义,除了名称?我在这里错过了什么吗?

编辑:是所涉及的每个表的 CREATE 语句。还有更多,但我们这里只需要 ft_booking 和 dm_date 表(文件的前两个表)。

0 投票
1 回答
258 浏览

greenplum - 全局缓存greenplum查询计划?

我想使用计划缓存来节省计划器成本,因为 OCRA/Legacy 优化器将花费数千万秒。

我认为会话级别的greenplum缓存查询计划,当会话结束或其他会话无法共享分析的计划时。更重要的是,我们不能一直保持会话,因为 gp 系统在 TCP 连接断开之前不会释放资源。

大多数主要的数据库缓存计划在第一次运行后,并使用该 corss 连接。

那么,是否有任何开关可以打开查询计划缓存交叉连接器?我可以在会话中看到,客户端计时统计与规划器给出的“总时间”不匹配?

0 投票
1 回答
75 浏览

greenplum - 自动选择旧版/OCRA 优化器?

对于大量小查询,set optimizer = OFF是减少延迟的好选择。但是我很难决定应该使用哪个语句?是否有任何服务器配置可以根据语句自动打开/关闭它?

0 投票
1 回答
2764 浏览

postgresql - Postgres 在枚举类型上使用部分索引来表示相等条件但不用于不相等

使用 PostgreSQL 9.6.9,我有:

  • 在某个表 xy 的列中使用的具有 3 个级别的自定义 SQL 枚举类型。
  • 表 xy 上此枚举的最高级别 (level3) 的复合部分索引。
  • 大量虚拟数据(超过 200000 行)

在控制台中使用EXPLAIN ANALYSE,我看到:

但:

除了不等式/相等条件外,查询完全相同。

数据库规划器是否无法看到 level2 以上只能是 level3,因此它可以使用部分索引?

为什么 Postgres 没有正确优化这个……这似乎是一些简单的逻辑事情。

0 投票
0 回答
88 浏览

postgresql - 为什么表中的不同数据可以以不同的性能进行处理?

我在使用 Postgres 10 数据库时遇到了一个奇怪的性能问题。

我有这样一张桌子:

我们有一个 Python 库(使用 psycopg2 驱动程序)来访问这个表。它对表执行简单的查询,其中一个用于批量下载内容,它看起来像这样:

我注意到,对于某些 ID,它的运行速度非常快,而对于其他 ID,它的运行速度要慢 4-5 倍。需要注意的是,该表中有两个主要的ID“类别”:第一个是2.7亿-5亿范围,第二个是100亿-1000.3亿范围。第一个范围是“快”,第二个范围是“慢”。除了更大的绝对数将它们从intto中提取出来之外bigint,第二个范围内的值更“稀疏”,这意味着在第一个范围内的值几乎是随之而来的(缺失值的“洞”很少),而在第二个范围内有更多“洞”(平均填充率为 30%)。

为了消除其他库的可能影响,我使用以下查询进行了综合测试:

我调整了请求的夹头的长度,以平均每个请求的 JSONB 的摘要长度。

此外,我计算返回的处理速率count(*)除以执行时间。第一个范围是 800-1050 行/秒,第二个范围是 120-250 行/秒。另一个指标是每次处理 JSON 的长度。由于查询中的主要困难似乎是处理 JSONB 数据,我假设在这两种情况下它必须平均相同。但不是:它是 7-10 MB/s 与 1.5-2.5 MB/s。

于是问题重现。虽然它在绝对值上变得更快(由于没有网络传输),但性能上的显着差异仍然存在。我比较了两个范围内查询的执行计划,它们看起来等效(EXPLAIN ANALYZE):

我看到的唯一区别是转换bigint应该是一次性的。

我错过了什么吗?如何调查(和修复)它?

更新 1:添加EXPLAINBUFFERS

更新 2:更多实验:

我对表中的所有数据进行了更多测试以利用上述方法。使用一个简单的程序,我迭代段的边界以最终处理两个范围内的所有数据。在此期间,我解析 EXPLAIN ANALYZE 的结果并收集以下一系列指标:

  • 缓冲区命中/读取表。
  • 缓冲区命中/读取索引。
  • 行数(从Index Scan...
  • 执行期限

根据上面的指标,我计算继承的指标:

  • 磁盘读取率:(索引读取 + 表读取)* 8192 / 持续时间。
  • 读取比率:(索引读取 + 表读取)/(索引读取 + 表读取 + 索引命中 + 表命中)
  • 数据率:(索引读取 + 表读取 + 索引命中 + 表命中)* 8192 / 持续时间

由于 ID 的“密度”在“小”和“大”范围内是不同的,因此我调整了块的大小,以便在这两种情况下每次迭代都获得大约 5000 行,尽管我的实验表明块大小并不重要.

上面发布的结果在整个第一个和第二个范围内都得到了确认(因此它不仅仅是由随机缓存的数据引起的)。

为了消除缓存影响,我用刷新缓冲区重新启动了 Postgres 服务器:

在此之后,我重复了测试并得到了一张几乎相同的照片。

我将上次测试中的系列渲染成图表并在此处发布:

“小”数字范围

这是“小”范围的图片。在整个测试中,磁盘读取速率统一在 10-11 MB/s 左右。

问题:为什么虽然我刷新了内存缓冲区,但命中率很高(读取率很低)?

“大”数字范围

这是“大”范围的图片。在我看来这很疯狂。在大多数情况下,磁盘读取速度约为 2 MB/s,但有时会跃升至 26-30 MB/s。读取率也变化很大。

在测试期间,我验证了磁盘读取速度,iotop发现它的指示非常接近我计算的指示。我不能说我一直在监视它,但是当它在第二个范围为 2 MB/s 和 22 MB/s 以及在第一个范围为 10 MB/s 时,我确认了它。我还检查了htopCPU 不是瓶颈,在测试期间约为 3%。

该问题在主服务器和从服务器上都可以重现。我的测试是在从属设备上进行的,而 DBMS 上没有任何其他负载,或者与 DBMS 无关的主机上的磁盘活动。

我唯一的假设是,由于虚拟化或其他原因,不同的数据片段以不同的速度被读取,但是......为什么它如此严格地限制在这些范围内?为什么在两台不同的机器上是一样的?

有任何想法吗?

0 投票
0 回答
94 浏览

sql - Postgres 查询计划器调优

我们有一个包含测量数据的 db (9.6)。相关查询涉及 3 个表:

  • aufnehmer(即传感器),5e+2 个条目,
  • zeitpunkt(即时间点),4e+6 个条目
  • wert(即值),6e+8 个条目

aufnehmer : zeitpunkt = m : n 以 wert 作为映射表。所有相关列都被索引。

以下查询

产生这个查询计划: 在此处输入图像描述

大约需要一秒钟。当结束日期增加一天并且查询更改为:

查询计划更改为 在此处输入图像描述

并且执行需要大约 1000 倍的时间。

因此,查询计划器似乎切换到先加入 aufnehmer 和 wert,这比先加入 zeitpunkt 和 wert 花费的时间要长得多。

知道是否可以强制保留第一个执行计划吗?我们已经增加了 work_mem 但它没有任何区别。

0 投票
0 回答
49 浏览

php - 与通过 Navicat 生成的查询计划相比,PHP 中的 Mysql 查询计划不同

在发布此内容时,我很困惑。我不明白为什么当我在 php 中触发 EXPLAIN 与在 Navicat 中为完全相同的查询触发 EXPLAIN 时,查询的查询计划是不同的。

询问:

解释 Navicat 中的输出:

  • 编号 - 1
  • select_type - 简单
  • 表 - sales_table
  • 分区 - NULL
  • 类型 - 参考
  • possible_keys - 客户 ID
  • 键 - 客户 ID
  • key_len - 22
  • 参考 - 常量
  • 行 - 1
  • 过滤 - 100
  • 额外 - NULL

解释从 PHP 触发时的输出:

  • 编号 - 1
  • select_type - 简单
  • 表 - sales_table
  • 分区 - NULL
  • 类型 - 全部
  • possible_keys - 客户 ID
  • 键 - 空
  • key_len - 空
  • 参考 - 空
  • 行 - 1772719
  • 过滤 - 10.00
  • 额外 - 使用 where

如您所见,解释输出有很大不同。由于这种差异,从我的 PHP 页面执行查询需要 4 倍的时间。

我尝试使用强制索引。但是,这也不起作用。

我发现了一篇相关的帖子——PHP 运行查询的时间比 MySQL 客户端长 90 倍。但是,我无法找到有关查询计划差异的任何信息。

这是一个仍在使用 mysql_query 的遗留应用程序。

  • PHP 版本 - 5.6.34-1+ubuntu16.04.1+deb.sury.org+1
  • mysqlnd 版本 - mysqlnd 5.0.11-dev - 20120503
0 投票
0 回答
1095 浏览

sql - 提高临时表插入的性能(有很多列)

我必须从选择查询中创建一个临时表#Trades。选择查询返回 77,987 行和大约 175 列(varchar、numeric、small int 和 int 的混合)。

我目前正在使用以下查询来创建临时表:

在此处输入图像描述

根据查询计划,表格插入花费的时间最多。

在此处输入图像描述

此外,估计行数与实际行数不匹配。

无论如何我可以提高用于创建#Trades 临时表的查询的性能吗?

PS:我尝试使用 create table 创建一个临时表,并将查询更改为插入到临时表中,但这并没有太大帮助。

0 投票
3 回答
112 浏览

sql - 如何使用嵌套在 OR 中的多个 AND 条件来索引 SQL

我想加快下面的sql(成本是19685.75)。我可以索引这个在 WHERE 语句中具有多个复杂嵌套 AND 条件并结合 OR 的 sql 吗?

表格文本包含以下字段和索引(其他一些字段未显示)

我为 created_at、lastmod 和 publication_date 添加了三个单一索引;以及这些字段的一个多列索引。

但是在 postgres EXPAIN 查询中,这个 where 子句仍然使用Seq Scan而不是Index Scan

我的问题是:
1. 是否可以让 postgres 对这个复杂的 SELECT 子句使用索引扫描?
2. 是否需要为每个 AND 子句创建一个多列索引?例如(publication_date, lastmod)在此原因中创建索引?

  1. 索引是否适用于搜索 IS NULL?搜索 IS NULL 的字段是否需要索引?

2018 年 11 月 4 日更新

当我尝试通过一一测试字段来最小化查询时,字段publication_datelast_mod触发索引分别扫描,而created_at不能:

是因为created_at是时间戳吗?但是为什么索引不适用于时间戳?

publication_date似乎触发索引扫描: