精华内容
下载资源
问答
  • KingbaseES查询计划剖析

    2021-11-18 18:17:27
    对于开发人员和数据库管理员来说,了解KingbaseES查询计划是一项关键技能。这可能是优化SQL查询的第一件事,也是验证优化的SQL查询是否确实实现期望结果的方式。 KingbaseES数据库中的查询生命周期 每个查询都会经历...
    1. 概述
      对于开发人员和数据库管理员来说,了解KingbaseES查询计划是一项关键技能。这可能是优化SQL查询的第一件事,也是验证优化的SQL查询是否确实实现期望结果的方式。
    2. KingbaseES数据库中的查询生命周期
      每个查询都会经历不同的阶段,了解下面周期的每个阶段,对理解数据库是很重要的。
      在这里插入图片描述

    第一阶段是通过JDBC/ODBC或通过其他方式如KSQL(客户端工具)连接到数据库。
    第二阶段是将查询转换为解析树的格式,就像 SQL 查询的编译形式。
    第三阶段是重写系统/规则系统。它采用从第二阶段生成的解析树,并以规划器/优化器可以开始在其中工作的方式重写它。
    第四阶段是最重要数据库的核心。规划器使得知执行器知道如何执行查询、使用什么索引、是否扫描较小的表以消除更多不必要的记录等问题。
    第五个也是最后一个阶段是执行器,它执行实际执行并返回结果。
    下面将描述第四阶段的工作内容。
    3. 数据设置
    首先建立一些表来运行本文的实验。
    CREATE TABLE TEST_TABLE AS
    select id, lpad(id,10,‘0’) code, md5(random()) name
    from generate_series(1, 1000000) id;
    该表包含1000000行记录。
    下面的大多数示例将基于上表。有意保持简单,专注于过程而不是表/数据的复杂性。
    4. 进入规划阶段
    KingbaseES数据库系统通过执行EXPLAIN命令,让用户可以在计划阶段看到实际发生的事情。
    5. KingbaseES解释一个查询
    explain select * from test_table limit 10;在这里插入图片描述
    通过使用EXPLAIN,可以在数据库实际执行查询计划之前查看它们。将在下面的部分中了解每一个的部分,先看看另一个扩展版本的EXPLAIN调用EXPLAIN ANALYZE。
    explain analyze select * from test_table limit 10;
    在这里插入图片描述

    与 不同EXPLAIN,EXPLAIN ANALYSE实际上在数据库中运行查询。这个选项对于了解计划者是否没有正确发挥其作用非常有帮助;即,从EXPLAIN和生成的计划是否存在巨大差异EXPLAIN ANALYZE。
    6. 什么是数据库中的缓冲区和缓存?
    这里讨论一个有意义的指标BUFFERS。它解释了有多少数据来自缓存,以及有多少必须从磁盘中获取。
    explain (analyze,buffers) select * from test_table limit 10 offset 20;
    在这里插入图片描述
    Buffers : shared hit=1意味着从 KingbaseES缓存本身获取了1个页面。
    explain (analyze,buffers) select * from test_table limit 100 offset 500;
    在这里插入图片描述
    Buffers: shared hit=2 read=4,显示4个页面来自磁盘。该read部分是显示有多少页面来自磁盘的变量,hit表示来自缓存。如果我们再次执行相同的查询(记住ANALYSE运行查询),那么所有数据现在都来自缓存。
    在这里插入图片描述
    KingbaseES使用一种称为 LRU(最近最少使用)缓存的机制将经常使用的数据存储在内存中。了解到 KingbaseES 的缓存机制,可以使用EXPLAIN (ANALYSE, BUFFERS)命令查看它是如何工作的。
    7. VERBOSE 命令参数
    Verbose 是另一个提供额外信息的命令参数。
    explain (analyze,buffers,verbose) select * from test_table limit 100 offset 500;
    在这里插入图片描述
    注意,Output: id, code, name是附加的。在复杂的查询计划中,将打印大量其他信息。默认情况下,COSTS and TIMING选项TRUE作为设置,除非您想将它们设置为FALSE。
    8. KingbaseES中的 FORMAT 解释
    KingbaseES能够以多种格式提供查询计划,例如JSON,这些计划可以用某种语言进行解析。
    explain (analyze,buffers,verbose,format json) select * from test_table limit 100 offset 5000;
    在这里插入图片描述
    同时还支持其他格式:TEXT(默认)、JSON、XML、YAML
    9. 总结EXPLAIN使用方式
    EXPLAIN 通常会开始使用的计划类型,主要用于生产系统。
    EXPLAIN ANALYSE用于运行查询以及获取查询计划。这是获得计划中的计划时间和执行时间细分以及与执行查询的成本和实际时间的比较。
    EXPLAIN (ANALYSE, BUFFERS) 在分析之上使用以获取来自缓存和磁盘的行/页数以及缓存的行为方式。
    EXPLAIN (ANALYSE, BUFFERS, VERBOSE) 获取有关查询的详细信息和附加信息。
    EXPLAIN(ANALYSE,BUFFERS,VERBOSE,FORMAT JSON)是以特定格式导出的方式;在这种情况下,JSON。
    10. 查询计划的元素
    无论复杂性如何,任何查询计划都有一些基本结构。在本节中,将重点关注这些结构,这将有助于以抽象的方式理解查询计划。
    11. 查询的节点
    查询计划由节点组成:在这里插入图片描述
    一个节点可以被认为是数据库执行的一个阶段。节点大多是嵌套的,如上图所示;在Seq Scan它之前和之上完成,然后应用该Limit子句。可以添加一个Where子句来理解多层次的嵌套。
    explain select * from test_table where code = ‘0002222’ limit 10 offset 500;
    在这里插入图片描述
     筛选ID > 10000 的行。
     使用过滤器进行顺序扫描。
     在顶部应用LIMIT条件。
    如您所见,数据库识别出只需要 10 行,并且一旦达到所需的 10 行就不会再进行扫描。当前,已关闭查询并行,SET max_parallel_workers_per_gather =0; ,以便计划更简单。
    12. 查询规划器中的成本
    成本是数据库查询计划的关键部分,由于它们的表示方式,这些成本很容易被误解。
    在这里插入图片描述
    需要注意的几个重要事项是:
     LIMIT条款的启动成本不为零。这是因为启动成本汇总到顶部,看到的是其下方节点的成本。
     总成本是一个衡量标准,与规划者的相关性比与用户的相关性更高。
     通常,顺序扫描在估计方面很模糊,因为数据库不知道如何优化它们。索引可以极大地加速带有WHERE子句的查询。
     Width很重要,因为一行越宽,需要从磁盘获取的数据就越多。
    如果我们实际运行查询,那么成本会更有意义。
    13. 数据库规划和执行
    计划和执行时间是仅使用EXPLAIN ANALYSE选项获得的指标。
    在这里插入图片描述
    Planner(Planning Time)根据各种参数决定查询应该如何运行,Executor(执行时间)运行查询。上面指出的这些参数是抽象的,适用于任何类型的查询。运行时间以毫秒表示。极少的场景,会出现Plan程序可能需要更多时间来计划查询,而执行程序需要更少时间。它们不一定需要彼此匹配,但如果它们差距很多,那么就要检查其原因了。
    在典型代表在线事务处理的 OLTP 系统中,任何计划和执行的总和应该小于 50 毫秒,除非它是分析查询/大量写入/已知异常。在典型的业务中,交易通常从数千到数百万不等。应始终非常仔细地观察这些执行时间,因为这些较小的成本较高的查询可能汇总起来并增加巨大的开销。
    14. 优化查询从这里出发
    已经涵盖了从查询生命周期到规划器如何做出决策的步骤,本文省略了像节点类型(扫描、排序、连接)这样的主题,因为它们交为复杂,另需文档说明。本文的目的是泛泛了解查询规划器的工作原理、影响其决策的因素以及KingbaseES 提供的工具以更好地理解规划器。
    【参考手册】
    《[系统管理][参考手册]KingbaseES客户端应用参考手册》、
    《[应用开发及迁移][服务器编程]SQL语句参考》

    展开全文
  • MySQL 查询计划 总结

    2021-01-19 02:56:51
    (一)查询计划 释义查询计划: SQL语句是怎样进行执行的使用 EXPLAIN 关键字可以模拟优化器执行 SQL 查询语句,从而知道 MySQL 是如何处理你的 SQL 语句的。分析你的查询语句或是表结构的性能瓶颈。用法: Explain+...

    (一)查询计划 释义

    查询计划: SQL语句是怎样进行执行的

    使用 EXPLAIN 关键字可以模拟优化器执行 SQL 查询语句,从而知道 MySQL 是如何处理你的 SQL 语句的。分析你的查询语句或是表结构的性能瓶颈。

    用法: Explain+SQL 语句。Explain 执行后返回的信息:

    9e81417df31ee42f839fb5b8092bd4d9.png

    (二)具体字段解释与demo

    1 id  :  select 查询的序列号,包含一组数字,表示查询中执行 select 子句或操作表的顺序。

    id 相同,执行顺序由上至下

    4d9b5a2b164e324fd9d30ac7c7214298.png

    id 如果相同,可以认为是一组,从上往下顺序执行;在所有组中,id 值越大,优先级越高,越先执行衍生 = DERIVED

    关注点:id 号每个号码,表示一趟独立的查询。一个 sql 的查询趟数越少越好。

    2 select_type  代表查询的类型,主要是用于区别普通查询、联合查询、子查询等的复杂查询

    SIMPLE

    简单的select 查询,查询中不包含子查询或者union

    PRIMARY

    查询中若包含任何复杂的子部分,最外层查询则被标记为Primary

    DERIVED

    在FROM列表中包含的子查询被标记为DERIVED(衍生) MYSQL会递归执行这些子查询,把结果放在临时表里

    SUBQUERY

    在select或where列表中包含了 子查询

    DEPEDENT SUBQUERY

    在select或where列表中包含了 子查询,子查询基于外层

    UNCACHEABLE SUBQUERY

    无法使用缓存的子查询

    UNION

    若第二个select 出现在UNION之后,则被标记为UNIONL 若UNION包含在from子句的子查询中,外层select将被标记为:DERIVED

    UNION RESULT

    从UNION表获取结果的SELECT

    3 table

    这个数据是基于哪张表的。

    4  type

    是查询的访问类型。是较为重要的一个指标,结果值从最好到最坏依次是

    system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index >ALL

    一般来说,得保证查询至少达到 range 级别,最好能达到 ref。

    system

    表只有一行记录(等于系统表),这是 const 类型的特列,平时不会出现,这个也可以忽略不计

    const

    表示通过索引一次就找到了,const 用于比较 primary key 或者 unique 索引。因为只匹配一行数据,所以很快 如将主键置于 where 列表中,MySQL 就能将该查询转换为一个常量

    eq_ref

    唯一性索引扫描,对于每个索引键,表中只有一条记录与之匹配。常见于主键或唯一索引扫描。

    ref

    非唯一性索引扫描,返回匹配某个单独值的所有行.本质上也是一种索引访问,它返回所有匹配某个单独值的行,然而,它可能会找到多个符合条件的行,所以他应该属于查找和扫描的混合体。

    range

    只检索给定范围的行,使用一个索引来选择行。key 列显示使用了哪个索引一般就是在你的 where 语句中出现了 between、、in 等的查询这种范围扫描索引扫描比全表扫描要好,因为它只需要开始于索引的某一点,而结束语另一点,不用扫描全部索引

    index

    出现index是sql使用了索引但是没用通过索引进行过滤,一般是使用了覆盖索引或者是利用索引进行了排序分组

    all

    Full Table Scan,将遍历全表以找到匹配的行。

    5 possible_keys

    显示可能应用在这张表中的索引,一个或多个。查询涉及到的字段上若存在索引,则该索引将被列出,但不一定被查询实际使用。

    6 key

    实际使用的索引。如果为NULL,则没有使用索引。

    7 key_len

    表示索引中使用的字节数,可通过该列计算查询中使用的索引的长度。 key_len 字段能够帮你检查是否充分的利用上了索引。ken_len 越长,

    说明索引使用的越充分。

    8 ref

    显示索引的哪一列被使用了,如果可能的话,是一个常数。哪些列或常量被用于查找索引列上的值。

    9 rows

    rows 列显示 MySQL 认为它执行查询时必须检查的行数。越少越好!

    10 Extra

    其他的额外重要的信息。

    Using filesort

    说明 mysql 会对数据使用一个外部的索引排序

    Using temporary

    使了用临时表保存中间结果,MySQL 在对查询结果排序时使用临时表

    Using index

    Using index 代表表示相应的 select 操作中使用了覆盖索引(Covering Index)

    Using where

    表明使用了 where 过滤

    Using join buffer

    使用了连接缓存

    impossible where

    impossible where

    select tables optimized away

    查询执行计划生成的阶段即完成优化。

    好几次。。。。。。

    展开全文
  • 文章目录 第七章 解释SQL查询计划存储在映射中的表发展计划阅读计划访问映射条件和表达式循环临时文件定义使用模块发送给处理的查询子查询、连接和联合计划分析添加一个索引添加字段到索引数据添加连接索引 ...

    第七章 解释SQL查询计划

    本章介绍由ShowPlan生成的InterSystems SQL查询访问计划中使用的语言和术语。

    存储在映射中的表

    SQL表存储为一组映射。
    每个表都有一个包含表中所有数据的主映射;
    表还可以有其他的映射,如索引映射和位图。
    每个映射可以被描绘成一个多维全局,其中一些字段的数据在一个或多个下标中,其余字段存储在节点值中。
    下标控制要访问的数据。

    • 对于主映射,RowIDIDKEY字段通常用作映射下标。
    • 对于索引映射,通常将其他字段用作前导下标,将RowID/IDKEY字段用作附加的较低级别的下标。
    • 对于位图,可以将位图层视为附加的RowID下标级别。但是,位图只能用于为正整数的RowID

    发展计划

    编译SQL查询会生成一组指令来访问和返回查询指定的数据。
    这些指令表示为. int例程中的ObjectScript代码。

    指令及其执行顺序受到SQL编译器中有关查询中涉及的表的结构和内容的数据的影响。
    编译器尝试使用表大小和可用索引等信息,以使指令集尽可能高效。

    查询访问计划(ShowPlan)是对结果指令集的可读翻译。
    查询的作者可以使用这个查询访问计划来查看将如何访问数据。
    虽然SQL编译器试图最有效地利用查询指定的数据,但有时查询的作者对存储的数据的某些方面的了解要比编译器清楚得多。
    在这种情况下,作者可以利用查询计划修改原始查询,为查询编译器提供更多的信息或更多的指导。

    阅读计划

    “ShowPlan”的结果是一系列关于访问和显示查询中指定的数据的处理的语句。
    下面提供了关于如何解释ShowPlan语句的信息。

    访问映射

    一个查询计划可以访问多个表。
    当访问一个表时,计划可以访问单个映射(索引或主映射)、两个映射(索引映射后面跟着主映射),或者,对于多索引计划,可以访问多个映射。

    在通过映射访问数据时,计划指示使用的下标。
    它还指示实际的下标值是什么:一个给定值、一组给定值、一个值范围,或该下标在表中显示的所有值。
    选择哪一个取决于查询中指定的条件。
    显然,访问单个或几个下标值要比访问该下标级别上的所有值快得多。

    条件和表达式

    当查询运行时,将测试查询指定的各种条件。
    除了前面提到的某些限制下标的条件外,ShowPlan输出没有显式地指示条件的测试。
    尽早测试条件总是最好的。
    测试各种条件的最佳地点可以从计划细节中推断出来。

    类似地,ShowPlan不详细描述表达式和子表达式的计算。
    除了简单之外,主要原因是在大多数数据库环境中,表和索引访问构成了处理的更重要方面;
    检索表数据的成本占总体查询成本的主要地位,因为磁盘访问速度仍然比CPU处理慢几个数量级。

    循环

    当访问一个表中的数据时,经常需要迭代地检查多个行。
    这样的访问是通过一个循环来指示的。
    每一次传递要执行的指令称为循环体。
    它们可以通过缩进直观地显示出来。
    涉及多个表的数据库访问通常需要循环中的循环。
    在这种情况下,每个循环级别都通过与前一个级别相比的进一步缩进表示。

    临时文件

    定义

    查询计划还可能指示需要构建和使用中间临时文件(TEMP-FILE)。这是本地数组中的“临时”区域。它用于保存临时结果以用于各种目的,如排序。就像映射一样,临时文件有一个或多个下标,可能还有节点数据。

    使用

    一些临时文件包含处理单个表的数据。在这种情况下,可以将构建临时文件视为对该表中的数据进行预处理。在读取这样的临时文件之后,可以访问源表的主映射,也可以不访问源表的主映射。在其他情况下,临时文件可能包含处理多个表的结果。在其他情况下,临时文件用于存储分组的聚合值、检查DISTINCT等。

    模块

    临时文件的构建,以及其他处理,可以委托给一个称为模块的独立工作单元。
    每个模块都被命名。
    当列出单独的模块时,该计划将指明调用每个模块的位置。
    当模块执行结束时,处理将在模块调用之后的下一条语句中继续进行。

    发送给处理的查询

    对于通过ODBC或JDBC网关连接链接的外部表,该计划显示发送到远程SQL gateway connection的查询文本,以从远程表检索所请求的数据。

    对于并行查询处理和分片,该计划显示发送到并行处理或在分片上处理的各种查询。
    还将显示用于每个查询的计划。

    子查询、连接和联合

    给定查询中的一些子查询(和视图)也可以单独处理。
    它们的计划在单独的子查询部分中指定。
    在计划中没有指明子查询部分被调用的精确位置。
    这是因为它们经常作为条件或表达式处理的一部分被调用。

    对于指定OUTER JOIN的查询,如果没有找到匹配的行,该计划可能指示可能生成的null行,以满足外部连接语义的要求。

    对于UNION,该计划可能指示将来自不同UNION子查询的结果行组合到一个单独的模块中,在该模块中可以对这些结果行进行进一步处理。

    计划分析

    在分析给定查询的计划时,应用程序开发人员有时可能会觉得不同的计划会更有效率。
    应用程序开发人员有多种方法来影响计划。

    首先,计划将受到在包含实际应用程序数据的环境中正确运行调优表的影响。
    在类源定义中手动定义一些Tune Table通常计算的值——例如表EXTENTSIZE、字段SELECTIVITY和映射BlockCount——也可以用于实现所需的计划。

    此外,分析计划可能表明对类定义的某些更改可能导致更有效的计划,例如:

    添加一个索引

    在某些情况下(尽管不总是),使用一个临时文件进行预处理可能意味着向原始表添加一个与临时文件具有相同或类似结构的索引将消除构建临时文件的需要。
    从查询计划中删除这个处理步骤显然可以使查询运行得更快,但这必须与更新表时维护索引所需的工作量进行平衡。

    添加字段到索引数据

    当计划显示正在使用的索引,然后是对主映射的访问时,这意味着将查询中使用的主映射字段添加到索引节点数据可能会为该查询生成更快的计划。
    同样,这必须与额外的更新时间以及添加到处理使用该索引的其他查询的额外时间进行平衡,因为索引会更大,因此需要更多的读取时间。

    添加连接索引

    当计划显示以特定顺序连接两个表时(例如,首先检索t1,然后使用连接条件t1.a=t2.b连接到t2),可能相反的表顺序会产生一个更快的计划。例如,如果t2有额外的条件,可以显著限制符合条件的行数。
    在这种情况下,在t1上添加一个t1索引。
    a将允许这样一个连接顺序。

    展开全文
  • 自spark 2.x 的sql以及申明行DataFrame APi以来,在spark查询数据越来越方便。仅仅用几行代码就能表达出复杂的查询逻辑以及实现复杂的操作。 这个api最大的优势在于用户不需要考虑太多的执行情况,自动有优化器优化...

    本文翻译自Be in charge of Query Excution in Spark SQL

    背景

    自spark 2.x 的sql以及申明行DataFrame APi以来,在spark查询数据越来越方便。仅仅用几行代码就能表达出复杂的查询逻辑以及实现复杂的操作。 这个api最大的优势在于用户不需要考虑太多的执行情况,自动有优化器优化出最有效率的执行方式去执行此次查询。而且有效的查询语句执行不仅是因为能够节约资源,而且能够减少终端用户等待结果的时间。
    Spark SQL 优化器实际上是很成熟的,尤其是随着3.0的到来,该版本会引入一些新特性,比如动态分支裁剪以及动态查询执行。 优化器是工作在查询计划内部的并且能够应用各种规则去优化查询计划。 例如能够改变transformation的执行顺序或者对于不影响最终结果的直接丢弃。虽然有很多优秀的优化,但是有些场景人是能够做的更好的。在这篇文章里,我们就来看一下特例,并且使用一些技巧来更好的执行查询计划。

    例子

    首先让我们来引入一个例子。加入我们有下列json格式的数据:

    {"id": 1, "user_id": 100, "price": 50}
    {"id": 2, "user_id": 100, "price": 200}
    {"id": 3, "user_id": 101, "price": 120}
    {"id": 4, "price": 120}
    
    

    每一个记录就像一个事务,而user_id这一列可能包含了很多重复的值(也可能包含null),除此之外还有其他的列来描述这个事务。 现在我们的查询是基于两个聚合的union操作,两个聚合的不同仅仅在于过滤条件的不同。在第一个聚合中我们想要获取价格总和小于50的用户,第二个聚合中我们想要获取价格综合大于100的用户,而且在第二个聚合中我们只考虑user_id不为null的。这个例子只是复杂例子的简化版本,但是这种复杂的例子是实际存在的。 以下是使用PySpark DataFrame API去表达我们想要的查询:

    df = spark.read.json(data_path)
    df_small = (
    df
    .groupBy("user_id")
    .agg(sum("price").alias("price"))
    .filter(col("price") < 50)
    )
    df_big = (
    df
    .filter(col("user_id").isNotNull())
    .groupBy("user_id")
    .agg(sum("price").alias("price"))
    .filter(col("price") > 100)  
    )
    result = df_small.union(df_big)
    

    计划的解释翻译

    对于优化查询性能的关键点在于能够去理解并解释翻译查询计划。计划的本身是能够通过Spark DataFrame explain函数展示出来的,或者如果计划已经是在运行了,我们可以通过Spark UI找到SQL这个tab,从而找到该计划。

    这个SQL tab中有已经完成的和正在运行的查询列表,所以选中我们的查询就能看到物理计划的图形化展示(这里我们移除了指标信息,这样能够使图⌚️更加简单)

    这个计划是树形结构,每个节点代表了一些操作,并且携带了一些执行信息。我们可以看到这个例子中我们有两个分支,和一个root分支在最底层,叶子在最顶层,也是执行开始的地方。scan json叶子节点代表从source中读取数据,然后这里有一对hashAggregate操作,代表着聚合。在这两个聚合操作之间有一个Exchange操作,代表着shuffle。filters操作携带着过滤条件信息。
    这个计划是一个典型的union操作,每一个dataframe都有一个新的分支,而且因为我们的例子中DataFrame是基于同样的数据源,这就意味着该数据源被scan了两次。现在我们能明白这里是存在优化的空间的.让数据源只被scan一次是一个很好的优化,尤其是在IO代价非常大的情况下。
    在这里我们想要实现的是重利用计算–scan数据和聚合的计算,因为在DataFrame上的操作是一样的,原则上计算一次就足够了。

    Cache缓存

    spark中一个典型的解决重新计算的方法是利用cache。在DataFrame中有一个cache函数:

    df.cache()
    
    

    这个是一个延迟转换,意味着只有在一些action触发后数据才会放到缓存层,在spark中Caching是一个很普通的操作,然而这是有限制的,特别是数据量很大和集群集资源非常紧张的情况下。而且我们必须意识到存储数据在缓冲层是需要额外的开销的,而且操作自身也是需要开销的。 在整个DataFrame df中调用cache操作并不能优化因为这个操作会缓存所有的列到存储中。一个更好的方法是只缓存选择被使用的字段。

    重新使用Exchage

    除了缓存,也还有另一种方法,这个方法不好用图形化描述,且基于重新利用Exchange。这个Exchange操作代表着用来集群之间移动数据的shuffle操作。shuffle操作一般在聚合,join,和一些转换操作中会用到。关于shuffle比较重要的事是spark总是会把shuffle 写的数据存储在磁盘,而且因为存储在磁盘,在必要的时候可以重新被使用。实际上spark在某个时机上会重新利用该数据。比如在spark发现从叶子节点到exchange节点的多个分支时重复的时候就会进行reuse操作[ReuseExchange规则],如果存在这种情况,说明我们这些重复的分支是有一样的计算,是可以重新被使用的。我们可以从计划中识别出来是否有这种场景,因为这些分支应该像以下这样:

    在我们的例子中,spark并不会重新利用Exchange,但是可以利用一些技巧而从使它被重新利用。为什么在我们的例子中Exchange不能被重新利用的原因是右边的分支有着user_id不为null的条件。该过滤条件是union操作的两个分支的唯一不同点,如果我们能消除这个不同点,spark将会重新利用EXchange。

    计划的改进

    我们怎么样才能分支是一样的呢?假如说是这个filer操作导致的,那我们可以颠倒filter的顺序,在聚合之后再进行过滤操作,因为这个对结果没有影响。然而这有一个陷阱。假如我们如下这样修改:

    df_big = (
     df.groupBy("user_id")
     .agg(sum("price").alias("price"))
     .filter(col("price") > 100)
     .filter(col("price").isNotNull())
    )
    

    再一次检查最终的查询计划,我们发现这个计划没有改变。解释很简单–这个filter操作被优化器移动了。

    从概念上来讲,存在着两种计划 逻辑计划和物理计划,这个时很好理解的。并且逻辑计划在转换为物理计划前会经过一个优化阶段。当我们改变了一些转换以后,直接反应在逻辑计划中。优化器会应用一系列的优化规则,这些规则通常是基于推断的。在我们的例子中,这个规则是PushDownPredicate,该规则是确保filters操作尽量被移动到靠近数据源的位置。它来源于进行过滤操作再进行数据集的操作效率更高。这个规则在大部分场景是很有用的。 然而在这里却不适用我们的例子。
    为了让filter在合适的位置,我们必须限制优化器。从spark 2.4以来我们可以通过配置项来让优化器排除某种规则:

    spark.conf.set(
    "spark.sql.optimizer.excludedRules",     "org.apache.spark.sql.catalyst.optimizer.PushDownPredicate")
    
    

    设置了这个以后,再一次运行查询语句,我们能看到filters操作的位置就如我们想的一样。这两个分支是一样的了,spark将会重新利用Exchange,数据将会只会被扫描一次,聚合操作也只会计算一次。
    在spark 3.0 情况有些不用,优化规则有不同的名字–PushDownPredicates,而且还有一个额外的规则用来下推filter-PushPredicateThroughNonJoin,所以实际上我们需要排除两个规则。

    总结

    我们看到通过这个,spark 开发者给了我们一种控制优化器的能力。但是也伴随着一种责任,我们列举了一下当使用这种技术的一些重点:

    • 当我们排除了PushDownPredicate,我们就得对这个查询中所有的filter负责,不仅仅是我们想要重新定位的filter。 这个还存在着另一种filter,这种filter很大概率出现的,例如分区filter,所以我们需要确保他们被放在合适的位置。
    • 限制了优化器,使用filter就是用户的工作了。在我们的例子中,加速查询是在IO比较昂贵的情况下,因为我们能实现数据只能被浏览一次,如果数据有很多列,这适用在文件格式不是列格式的青情况下,像json或者csv格式
    • 如果数据集很小,就不值得控制优化器了,反而cache能达到同样的效果。然而当数据集很大的时候,存储数据的额外开销就很明显了。从另一方面说,重新利用Exchange就没有额外的开销了,因为shuffle数据都存储在磁盘
    • 这个技术基于spark内部的行为,并没有官方文档,并且如果以后功能上有改动,很难去察觉。在我们的例子中,在spark 3.0中是有改动的,首先规则被重命名,并且加上了另一个规则

    结论

    我们知道如果要实现优化的前提是我们能够理解查询计划。spark的优化器通过一系列的推导规则能够很好的优化我们的查询。然而这里也有一些场景优化规则是不适用的。 有时候查询重写很好,有时候不好,因为重写查询将会实现不同的逻辑计划,并且我们不能直接控制被执行的物理计划。因为从spark 2.4以来,我们可以通过配置excludedRules来限制优化器,从未来定制了一些常规的物理计划。
    在很多场景中,依赖于优化器我们可以得到固定的计划,并且有一个高效的执行。然而 这里有一些性能压力,这里我们可以检查最终的计划,并且查看是否可以通过限制优化器来进行优化。

    展开全文
  • 查看MySQL的查询计划是分析查询的重要方法,可以通过使用EXPLAIN语句来确认优化器将采取哪种查询计划,是否与你的预期一致。如何使用EXPLIAN?使用它有两种方式:直接在查询语句之前直接加上EXPLAIN即可。EXPLAIN...
  • PostgreSQL查询计划剖析

    2021-07-01 21:57:56
    目录 介绍 PostgreSQL数据库中的查询生命...了解PostgreSQL查询计划对于开发人员和数据库管理员来说都是一项关键技能。这可能是我们开始优化查询的第一件事,也是验证我们优化的查询是否确实按照我们期望的方式优化
  • 文章目录 第八章 解释SQL查询计划(一)SQL语句创建SQL语句操作其他SQL语句操作List SQL语句列表列计划状态SQL语句文本陈旧的SQL语句数据管理(DML)SQL语句select命令 第八章 解释SQL查询计划(一) SQL语句 这个SQL...
  • oracle的查询计划

    2021-04-30 09:53:14
    oracle里面的查询计划的使用要比mysql的稍微复杂些。1。执行$ORACLE_HOME/rdbms/admin/utlxplan.sql,创建PLAN_TABLE表2。在sqlplus直接显示执行计划SQL>set timing on --显示执行时间SQL>set autotrace on --...
  • 文章目录 第八章 解释SQL查询计划(二)SQL语句的详细信息声明的细节部分性能统计数据编译设置部分例程和关系部分查询SQL语句导出和导入SQL语句导出SQL语句导入SQL语句查看和清除后台任务 第八章 解释SQL查询计划...
  • targetSize=min(maxTargetSize,advisoryPartitionSizeInBytes) 3、动态调整join策略(Dynamically switching join strategies) spark.sql.adaptive.localShuffleReader.enabled 默认true 优化类型:逻辑计划 ...
  • https://www.iteblog.com/archives/9806.html
  • 在Spark SQL中查询计划是理解查询执行的入口点,它携带了大量的信息,并且能够洞察查询是怎么执行的。在大的负载下或者执行的任务很长的时候,这些信息很重要的。从查询计划的信息我们可以发现哪些是低效的并且能够...
  • Greenplum查询计划评估

    2020-12-19 12:45:18
    如何看查询计划?若一个查询表现出很差的性能,查看查询计划可能有助于找到问题点。下面是 一些需要查看的东西: 计划中是否有一个操作花费时间超长?查询计划中是否有一个操作花费 了大部分的处理时间?例如,如果...
  • 在分布式环境下,构建相应的示例表,通过发起分布式查询,实际理解CBO如何确定局部执行代价,并利用相关优化技术的理论方法得到最优的执行计划
  • GBase 8a EXPLAIN显示查询计划MATION介绍
  • 数据库执行查询计划详细代码分析

    千次阅读 2021-09-16 17:03:15
    查询调用的函数栈: main()->PostmasterMain()->ServerLoop()->BackendStartup()->BackendRun()->PostgresMain()->exec_simple_query()→ 其中的postgresmain函数的分析进入下: //...
  • KingbaseES 查询计划剖析 关键字: Explain,让阅读者迅速了解关键点,同时便于互联网检索,引流 概述 了解KingbaseES查询计划对于开发人员和数据库管理员来说都是一项关键技能。这可能是优化SQL查询的第一件...
  • 最近面试过程中被面试官抛了一个问题,说曾经有一个线上出现的奇怪的问题,主库和从库各种配置是一致的,当数据量比较大的时候,某些时候同样的查询,在从库里的执行计划执行成功了,而主库里没有执行这个执行计划,...
  • 查看Mysql执行计划

    2021-01-18 18:54:01
    1、MySQL语法MySql提供了EXPLAIN语法用来进行查询分析,在SQL语句前加一个”EXPLAIN”即可。默认情况下Mysql的profiling是关闭的,所以首先必须打开profilingset profiling="ON"mysql> show variables like “%...
  • DBMS首先解析SQL语句得到逻辑计划,然后为逻辑计划中的每个算子选择效率最高的物理执行方式,即物理查询计划。逻辑计划优化和物理计划优化统称为查询优化,是DBMS中最难的部分,它决定了一条SQL语句的执行效率。 ...
  • 在计算出逻辑计划并优化后,我们将派生出多个不同的物理执行计划。这些不同的物理计划会产生不同的执行代价,因此,一般在执行之前会进行代价估计,然后执行引擎将选择代价最小的物理计划。根据代价,将确定从逻辑...
  • 通过观察执行计划,发现之前的执行计划在很多大表连接的部分使用了Hash Join,由于涉及的表中数据众多,因此查询优化器选择使用并行执行,速度较快。而我们优化完的执行计划由于索引的存在,且表内数据非常大,过滤...
  • mysql explain执行计划详解

    千次阅读 2021-01-28 02:18:25
    1)、id列数字越大越先执行,如果说数字一样大,那么就从上往下依次执行,id列为null的就表是这是一个结果集,不需要使用它来进行查询。2)、select_type列常见的有:A:simple:表示不需要union操作或者不包含子查询...
  • **测试发现:**用的同一个SQL去查询,执行计划不一样,有一个是走了索引,有一个没走,就不太明白是怎么回事。 这个表的组合索引为(D_REPORT_DATE,C_PORT_CODE,C_REPORT_TEMPLATE,C_ELEMENT_CODE)四个字段 其中D_...
  • 查看执行计划二、查询计划重用三、 自适应计划 一、执行计划查看 示例:执行计划是 SQL 语句的执行方式,由查询优化器为语句设计的执行方式,交给执行器去执行。在 SQL 命令行使用 EXPLAIN 可以打印出语句的执行...
  • 我们基于这个框架构建了特定于关系查询处理的库(例如,表达式、逻辑查询计划),以及处理查询执行的不同阶段的几组规则:分析(Analysis)、逻辑优化(Logical Optimizations)、物理计划(Physical Planning)以及...
  • 1)、id列数字越大越先执行,若是说数字同样大,那么就从上往下依次执行,id列为null的就表是这是一个结果集,不须要使用它来进行查询。2)、select_type列常见的有:A:simple:表示不须要union操做或者不包含子查询...
  • Oracle的任务计划

    2021-05-04 00:36:57
    有时候我们为了某个需求需要定期的去执行一个任务或操作,那么这时我们会想到任务计划。没错,第一种方法我们可以利用系统的计划任务去执行某个程序。如果我们是想在数据库中 定期的去处理数据,那么我们可以用...
  • mysql的计划任务

    2021-02-07 19:34:20
    1、查看是否开启了计划任务的支持SHOW VARIABLES LIKE 'event_scheduler';2、开启计划任务SET GLOBAL event_scheduler = ON;3:创建计划任务创建event语法:CREATE EVENT [ IF NOT EXISTS ] event_nameON SCHEDULE ...
  • mysql的查询缓存

    2021-01-19 18:32:38
    很多数据库产品能够缓存查询的执行计划,就是说,下一次同类型的sql,可以不通过sql解析和执行计划生产的过程。mysql还有另一种缓存机制,就是缓存完整的select查询结果。就是下一次查询命中缓存的话,会直接返回...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 299,133
精华内容 119,653
关键字:

查询计划