问题标签 [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.
sql - sqlite 选择错误的查询计划
考虑以下示例:
此查询创建没有 rowid 列的表并插入值(x,x),其中 1000 < x < 2000。为了帮助查询规划器,让我们运行 ANALYZE。
两种情况下的输出都是:0|0|0|SEARCH TABLE t1 USING COVERING INDEX t1b (b>? AND b<?)
但是,使用索引(对于第一个查询)是没有意义的,因为无论如何我们都必须遍历整个表,所以普通的 SCAN TABLE 似乎更有效。正是以这种方式使用 rowid 的表工作:
在这种情况下,输出将是:0|0|0|SCAN TABLE t1
和0|0|0|SEARCH TABLE t1 USING INDEX t1a (a>? AND a<?)
那么,任何人都可以解释查询计划器如何优化 WITHOUT ROWID 表的查询吗?
database - Postgres 在几乎每个查询中都使用 primary_key 索引
我们正在将我们的 postgres 数据库从版本 9.3.14 升级到 9.4.9。我们目前处于测试阶段。我们在测试时遇到了一个问题,当数据库更新到 9.4.9 时会导致 CPU 使用率过高。有些查询 Postgres 9.4 正在使用 primary_key_index 而有更便宜的选项。例如,为以下查询运行解释分析:
给出了这个:
虽然 9.3.14 中相同查询的查询计划给出了这样的:
如果我从查询中删除 ORDER BY 子句,则查询可以使用适当的索引正常工作。我可以理解,在这种情况下(使用 ORDER BY),规划器正在尝试使用主键索引来扫描所有行并获取有效行。但显然使用 sort 显然要便宜得多。
我已经探索过像enable_indexscan和enable_seqscan这样的 Postgres 参数,它们默认是在. 我们希望将其留在数据库中以决定进行索引扫描或顺序扫描。我们还尝试调整Effective_cache_size、random_page_cost和seq_page_cost。enable_sort也打开了。
它不仅发生在这个特定的查询中,而且还有一些其他查询正在使用 primary_key_index 而不是其他可能的有效方法。
PS:
postgresql - 使用 pl/pgsql 进行查询计划缓存
我无法理解查询计划缓存如何用于 pl/pgsql。
我想用JOIN
s 和IF
s 构建多合一查询,因此我将有多个不同的查询参数,并且我将在多个表中进行搜索。
起初我以为使用pl/pgsql会为每个参数组合产生不同的计划,事实并非如此,因为我有不止一个表
直接出现在 PL/pgSQL 函数中的 SQL 命令必须在每次执行时引用相同的表和列;也就是说,您不能将参数用作 SQL 命令中的表或列的名称。为了绕过这个限制,您可以使用 PL/pgSQL EXECUTE 语句构造动态命令——代价是执行新的解析分析并在每次执行时构造一个新的执行计划。 从这里
我猜每次执行新的分析都会减慢速度。如果我不使用EXECUTE
then
如果语句没有参数,或者执行了很多次,SPI 管理器将考虑创建一个不依赖于特定参数值的通用计划,并将其缓存以供重复使用。通常,只有当执行计划对其中引用的 PL/pgSQL 变量的值不是很敏感时,才会发生这种情况。如果是这样,那么每次制定计划都是一种净赢。从这里
那我应该使用通用计划吗?是更快,还是因为每次都没有计划而变慢?至少它们被缓存了。我的查询对它们的变量很敏感,因为它们是动态的,但是什么
如果是这样,那么每次制定计划都是一种净赢。
实际上是什么意思?EXECUTE
每次使用/plan 比通用的好还是坏?“净赢”让我感到困惑。
如果一个通用计划不准确并且EXECUTE
/planning 每次都比较慢,那么为什么还要使用 pl/pgsql 呢?然后我可以用几个 if 编写一个简单的查询。
底线是,我无法断定在速度和计划缓存方面EXECUTE/plan each time
是更好还是最差generic cached plan
。请解释和建议,我很困惑。
作为参考,这就是我正在创建的。像现在一样工作,但将添加更多的 IFmytables
和mywhere
谢谢
sql - 查询内联与展平
我一直在互联网上一遍又一遍地挖掘,找不到任何合理的答案。SQL查询中的内联和展平有什么区别?我确实可以互换使用两者,最终它们会导致相同的结果 - 一个大的单个查询,而不是很多原子查询。但也许定义上有所不同?例如,内联仅指函数,展平意味着将子查询转换为仅按此处的立场加入?但是在另一个来源中可以找到一个完全不同的转换示例。
postgresql - Posgres 10:在不可变函数中“欺骗”now()。一个安全的想法?
我的应用程序向白水划船者报告降雨和流量信息。Postgres 是我的数据存储,用于以 15 分钟为间隔的仪表读数。随着时间的推移,这些表变得相当大,并且 Postgres 10 中范围分区的可用性激励我离开我的共享托管服务并在 Linode 从头开始构建服务器。在我将读数分成 2 周的块后,我对这些大表的查询变得更快。几个月后,我检查了查询计划,非常惊讶地发现在查询中使用 now() 会导致 PG 扫描我分区表上的所有索引。有没有搞错?!?!分区数据的目的不是为了避免这种情况吗?
这是我的设置:我的分区表
我每两周创建一次分区,所以到目前为止我有大约 50 个分区表。我的分区之一:
然后每个分区在 gauge_id 和 reading_time 上建立索引
我有很多疑问,比如
正如我所提到的,postgres 会为每个“子”表扫描 reading_time 上的所有索引,而不是仅查询在查询范围内具有时间戳的子表。如果我输入文字值(例如 precip.reading_time > '2018-03-01 01:23:00')而不是 now(),它只会扫描相应子表的索引。我已经阅读了一些内容,并且我知道 now() 是易变的,并且规划者不会知道查询执行时的值是什么。我还读到查询计划很昂贵,因此 postgres 缓存计划。我可以理解为什么 PG 被编程来做到这一点。但是,我读到的一个反驳论点是,重新计划的查询可能比最终忽略分区的查询便宜得多。我同意——在我的情况下可能就是这种情况。
作为一种变通方法,我创建了这个函数:
注意 IMMUTABLE 语句。现在,当发出类似的查询时
select * from stream
where gauge_id = 2142 and reading_time > hours_ago2(-3)
and reading_time < hours_ago2(0)
PG 只搜索存储该时间范围内数据的分区表。这是我一开始设置分区时的目标。嘘。但这安全吗?查询计划器是否会缓存 hours_ago2(-3) 的结果并在接下来的几个小时内一遍又一遍地使用它?缓存几分钟就好了。同样,我的应用程序报告降雨和流量信息;它不处理金融交易或任何其他“关键”类型的数据处理。我已经测试过像 select hours_ago2(-3) 这样的简单语句,它每次都会返回新值。所以看起来很安全。但真的是这样吗?
postgresql - 将 now() 作为参数传递给函数时如何进行评估
我有一个表,该表在带有时区字段的时间戳上进行范围分区。我很惊讶地发现以下 where 条件导致规划器查询分区中的每个“子”表:
据我所知,计划器不知道 now() 在执行时会是什么,因此它会生成查询每个子表的计划。这是可以理解的,但这违背了首先设置分区的目的!如果我发出 reading_time > '2018-03-31',它只会对具有满足这些条件的数据的表进行索引扫描。
如果我创建以下函数会发生什么
然后我可以用
now() 什么时候被评估?或者,换句话说,文字时间值(例如,2018-03-31 1:01:01+5)是否被传递到函数中?如果是字面值,那么 Postgres 只会查询相应的子表,对吧?但是,如果它在函数内部评估 now(),那么我将回到扫描每个子表的索引的计划。似乎很难看到规划者在函数中做了什么。那是对的吗?
mysql - 具有不同参数的相同格式查询在 MySQL 8.0 中具有完全不同的执行时间
编辑:我现在已经解决了这个问题。感谢里克詹姆斯的帮助!另外:它不是解决方案的一部分,但是您对前缀索引是 100% 正确的。当我把它们拿出来时,性能实际上略有上升。
. . .
我遇到了一个奇怪的数据库问题,我无法解决这个问题,我希望这个聪明的蜂巢思维可以帮助我。简而言之,我发现尽管格式相同,但对我的数据库的一些查询非常慢,而其他查询几乎是即时的。例如,这个查询:
在 0.06 秒内返回结果。足以满足我的需求。但是这个查询:
这里唯一的区别在于搜索参数。但是第二个查询需要9 多分钟才能执行。如果使用“LIKE”而不是“=”则更长。当然,我的数据库中的 'Edward's' 比 'Ruth's' 多,但仅凭这一点肯定不能解释为什么第二个查询比第一个慢几个数量级?如您所见,该查询使用自联接。我很欣赏这些可能不是最有效的方法,但它们可以满足我的需要,并使我的前端代码更简单。大多数时候,它们工作得很好。
这是第一个(快速)查询的解释:
这是第二个(慢)查询的解释:
我知道这几乎是不可能阅读的,但我一生都无法弄清楚如何将表格布局中的任何内容粘贴/导入到该站点中...
重要的是,据我所知,这两个 EXPLAIN 显示了功能相同的查询计划!然而,一个比另一个快得多。计划者如何订购这些陈述可能有什么问题吗?我对 SQL 相当有能力,但是这个查询规划器/索引的东西对我来说对黑魔法的研究有点太远了。有人可以帮忙吗?
我试过添加和删除索引。我尝试使用 FORCE INDEX 重写查询,但这只会让它们变慢。我在这里束手无策。
我唯一能想到的可能是,如果自连接的两侧都足够大(即,搜索一个非常常见的名字和一个非常常见的姓氏),那么两者的组合会溢出一些内存缓冲区某处,而是在磁盘上处理。这似乎是唯一会在某些情况下导致如此急剧放缓的事情。因此,这里有一些来自正在搜索的主(即最大)表的指示性相关数字。
在主数据表(EXPLAIN 中别名为 prp)中,有 24,771 条记录,其 Property_Class 对应于“First_Name”,Property_Value 为“Edward”,有 567 条记录,Property_Class 对应于“Last_Name”,Property_Value 为“雅培。搜索这些参数的查询需要很长时间才能执行,并且通常会在完成之前使 Web 服务器超时。
相反,有 916 条 Property_Class 对应于“First_Name”且 Property_Value 为“Ruth”的记录,以及 15,054 条 Property_Class 对应于“Last_Name”且 Property_Value 为“Davies”的记录。搜索这些参数的查询需要 0.6 秒才能执行。
如您所见,这两个查询可能涉及相似数量的交叉匹配(约 14,000,000)。然而,一个是冰川,另一个不是。
无论如何,我已经尝试在 my.ini 中增加任何可能听起来的缓冲区类型变量,看看是否有帮助,但鉴于我真的不知道自己在做什么,我有点不愿意在这方面过于努力地尝试. 我更像是一名编码员而不是数据库服务器管理员!
因此,如果有人对我有一些见解,我会很高兴听到它!
感谢您的时间。
编辑:用于将 Property_Type、Person 和 Property_Value 拼接成一个连贯条目的 VIEW 如下:
以下是我认为相关表的 CREATE TABLE 语句:
..
编辑:哎呀......你是对的,里克詹姆斯......这些表定义在一个单独的 SQL 脚本中,所以我忘记了它们。道歉。
sql - 为什么拆分 ID 查找会导致不同的计划/性能
我有 2 个表:tbl_Token(约 1 亿行)和 tbl_EntryTokenSummary(约 37.5 亿行)
我试图理解为什么以下两种情况会导致不同的“网络”计划。我真的不明白为什么场景 1 甚至引用非聚集索引,它不应该是相关的。
我认为可以说性能是 1418 次扫描的结果,但为什么要这样做呢?
这将导致以下消息输出:
而这个计划: QueryPlan Scenario 1
但是,如果我分解 TokenId 查找,结果会发生显着变化:
产生更好的输出:
编辑:
在查看表设置时,我意识到我没有设置主键,只设置了一个分区聚集索引(实际上是唯一的,但没有标记为唯一)。
仅仅添加主键实际上使事情变得更糟,但是一旦我删除了所有索引并添加回主键(作为分区/集群),查询优化器计算出一个更正确的计划来做完全相同的事情。
原始查询计划:https ://www.brentozar.com/pastetheplan/?id=Hku0KKH3f
更新的查询计划(在主键之后):https ://www.brentozar.com/pastetheplan/?id=HJu3kwo2f
旁注:我被定向到此链接作为对生成的计划的解释: https ://sqlperformance.com/2014/01/sql-plan/starjoininfo-in-execution-plans
mongodb - 相同的 mongodb 查询给出不同的解释计划
我有两个 mongo 查询,查询中唯一的变化是 MercerId 字段仍然是两个查询给我不同的获胜计划。
第一次查询
上述查询的输出
}
第二次查询
上述查询的输出
}
如您所见,唯一的参数差异是merchantId,仍然解释给出了不同的获胜计划,IXSCAN 也显示了使用的不同索引。在第一个查询中使用created_1_merchantId_1索引,在第二个查询中使用id索引。第一个查询需要 40 秒才能得到结果,而第二个查询需要 1 秒。快速将受到高度赞赏。