DM达梦数据库--查询优化

数据库执行一条语句有多种方式,为了选择最优的执行方式,产生了查询优化器。查询 优化器分析语句运行时的所有因素,选择最优的方式去执行,提高了查询效率。因此,查询 优化是数据库执行SQL语句的重要过程,决定了数据库的查询性能。
1、优化目标
达梦数据库查询优化器的优化目标为最快响应时间。通过设置参数FIRST_ROWS来决 定优先返回多少条记录给用户,而不需要等待全部结果确定后再输出,FIRST_ROWS设置 范围为1~1000,单位为行。例如:FIRST_ROWS = 10,意思是查询出10条结果就立即 返回给用户。可以根据实际情况,调整参数值。
2、查询优化器
查询优化器通过分析可用的执行方式和查询所涉及的对象统计信息来生成最优的执行 计划。此外,如果存在HINT优化提示,优化器还需要考虑优化提示的因素。
查询优化器的处理过程包括:
1.优化器生成所有可能的执行计划集合;
2. 优化器基于字典信息的数据分布统计值、执行语句涉及到的表、索引和分区的存储 特点来估算每个执行计划的代价。代价是指SQL语句使用某种执行方式所消耗的 系统资源的估算值。其中,系统资源消耗包括I/O、CPU使用情况、内存消耗等;
3. 优化器选择代价最小的执行方式作为该条语句的最终执行计划。
优化器所做的操作有:查询转换、估算代价、生成计划
1>查询转换
查询转换是指把经过语法、语义分析的查询块之间的连接类型、嵌套关系进行调整,生 成一个更好的查询计划。常用的查询转换技术包括过滤条件的下放、相关子查询的去相关性。
1.过滤条件下放:在连接查询中,把部分表的过滤条件下移,在连接之前先过滤,可 以减少连接操作的数据量,提升语句性能;
2. 相关子查询的去相关性:把与子查询相关的外表与内表采用半连接的方式执行,放 弃默认采取的嵌套连接方式,对性能有较大提升。
2>估算代价
估算代价是指对执行计划的成本进行估算。执行节点之间的代价值相关性较强,一个执 行节点的代价包括该节点包含的子节点代价。代价衡量指标包括选择率、基数、代价。 选择率是指满足条件的记录占总记录数的百分比。记录集可以是基表、视图、连接或分
组操作的结果集。选择率和查询谓词相关,如name =‘韩梅梅’;或者是谓词的连接,如 name ='韩梅梅’and no =‘0123’。一个谓词可以看作是一个过滤器,过滤掉结果集中 不满足条件的记录。选择率的范围从0到1。其中,0表示没有记录被选中,1表示行集中 所有记录都被选中。
如果没有统计信息,则优化器依据过滤条件的类型来设置对应的选择率。例如,等值条 件的选择率低于范围条件选择率。这些假定是根据经验值,认为等值条件返回的结果集最少。
如果有统计信息,则可以使用统计信息来估算选择率。例如,对于等值谓词(name =‘韩 梅梅’),如果name列有N个不同值,那么,选择率是N分之一。
基数是指整个行集的行数,该行集可以是基表、视图、连接或分组操作的结果集。 代价表示资源的使用情况。查询优化器使用磁盘I/O、CPU占用和内存使用作为代价 计算的依据,所以代价可以用I/O数、CPU使用率和内存使用一组值来表示。所有操作都 可以进行代价计算,例如扫描基表、索引扫描、连接操作或者对结果集排序等。
访问路径决定了从一个基表中获取数据所需要的代价。访问路径可以是基表扫描、索引 扫描等。在进行基表扫描或索引扫描时,一次I/O读多个页,所以,基表扫描或索引全扫 描的代价依赖于表的数据页数和多页读的参数值。二级索引扫描的代价依赖于B树的层次、 需扫描的叶子块树以及根据rowid访问聚集索引的记录数。
连接代价是指访问两个连接的结果集代价与连接操作的代价之和。
3、生成计划
生成计划指计划生成器对给定的查询按照连接方式、连接顺序、访问路径生成不同的执 行计划,选择代价最小的一个作为最终的执行计划。
连接顺序指不同连接项的处理顺序。连接项可以是基表、视图、或者是一个中间结果集。 例如表t1、t2、t3的连接顺序是先访问t1,再访问t2,然后对t1与t2做连接生成结 果集r1,最后把t3与r1做连接。一个查询语句可能的计划数量是与FROM语句中连接项 的数量成正比的,随着连接项的数量増加而増加。
4、连接
查询语句中FROM子句包含多个表时,我们称为连接查询。如SELECT * FROM t1,t2 就是连接查询。
生成连接查询的执行计划,需要考虑三方面因素:
1.访问路径
对于每张表米用何种方式来获取数据。例如:全表扫描、索引扫描等。
查询优化器会估算每种扫描方式的代价,选择代价较小的访问路径。
2.连接方式
确定两张表之间采用哪种连接方式。例如:哈希连接、嵌套连接、归并连接、外连接。
等值连接条件一般会选择哈希连接;非等值连接条件会采用嵌套连接;连接列均为索引 列时,会采用归并连接。
1)嵌套连接:两张表进行非等值连接时会选择嵌套连接。相当于两张表进行笛卡尔集 操作。此时,优化器会选择一张代价较小的表作为外表(驱动表),另一张表作为内表,外 表的每条记录与内表进行一次连接操作。
2)哈希连接:两张表进行等值连接时会选择哈希连接。以一张表的连接列为哈希键, 构造哈希表,另张表的连接列进行哈希探测,找到满足条件的记录。由于哈希命中率高,因 此,在大数据量情况下,哈希连接的效率较高。哈希连接的代价是建立哈希表和哈希探测的 代价。
3)归并连接:两张表的连接列均为索引列,则可以按照索引顺序进行归并,一趟归并 就可以找出满足条件的记录。如果查询列也属于索引列的子集,则归并连接只需扫描索引, 会有更好的性能表现。在两表连接条件不是等值(如<,<=,>,>=)情况下时,归并排序 连接很有用。
4)外连接:外连接分为左外连接、右外连接、全外连接。作为外表的数据会全部返回, 如果没有与外表匹配的记录,则填充NULL值。右外连接与左外连接的处理过程类似,只是 外表不同,一个是左表,一个是右表。全外连接是进行左外连接和右外连接,返回两次外连 接的union结果集。
例1:左外连接:*
SELECT * FROM t1 LEFT OUTER JOIN t2 ON t1.c1=t2.d1;
例1中t1表为外表(左表),如果t2表中不存在与t1.c1相等的记录,
则t2表的该行记录用NULL填充。右外连接与左外类似。
例2:全外连接*
SELECT * FROM t1 FULL OUTER JOIN t2 ON t1.c1=t2.d1;
例2中分别以t1为左表进行左外和右外连接,两次结果进行union,返回最终结果。
子查询会转换成半连接。共有四种半连接方式:哈希半连接、索引半连接、嵌套半连接、 归并半连接。等值连接条件会选择哈希\索引\归并半连接,非等值连接条件会选择嵌套半连接。
1)哈希半连接:以外表的连接列为KEY构造哈希表,内表的连接列进行探测来查找 满足连接条件的记录;
2)索引半连接:如果子查询的连接列为索引前导列,可采用索引半连接。处理过程为 外表的数据对子查询使用索引查找,返回满足条件的记录;
3)归并半连接:如果相关子查询的连接条件列均为索引列,可采用归并半连接。按照 索引顺序,对外表、内表进行同步扫描,返回满足条件的记录;
4)嵌套半连接:如果连接条件为非等值,可转换为嵌套半连接。处理过程为外表的每 条记录去遍历内表,返回满足条件的记录。
3.连接顺序
当超过2张表进行连接时,就需要考虑表之间的连接顺序。不合适的连接顺序对执行 效率有较大影响。一般原则是,经过连接可以产生较小结果集的表优先处理。
一个连接查询通常会对应多个执行计划,查询优化器会根据优化规则、代价估算挑选最 优的执行计划。
5、统计信息
对象统计信息描述数据是如何在数据库中存储的。统计信息是优化器的代价计算的依 据,可以帮助优化器较精确地估算成本,对执行计划的选择起着至关重要的作用。
达梦数据库的统计信息分三种类型:表统计信息、列统计信息、索引统计信息。通过直 方图来表示。统计信息生成过程分以下三个步骤:
1.确定采样的数据:根据数据对象,确定需要分析哪些数据。
1)表:计算表的行数、所占的页数目、平均记录长度
2)列:统计列数据的分布情况
3)索引:统计索引列的数据分布情况
2.确定采样率
根据数据对象的大小,通过内部算法,确定数据的采样率。采样率与数据量成反比。
3.生成直方图
有两种类型的直方图:频率直方图和等高直方图。根据算法分析表的数据分布特征, 确定直方图的类型。频率直方图的每个桶(保存统计信息的对象的高度不同,等高 直方图每个桶的高度相同。例如,对列生成统计信息,当列值分布比较均匀时,会采用等高直方图,否则,采用频率直方图。
在执行查询时,如果数据对象存在统计信息,代价算法可以根据统计信息中的数据,比 较精确地计算出操作所需花费的成本,以此来确定连接方式、对象访问路径、连接顺序,选 择最优的执行计划。
用户也可以通过修改OPTIMIZER_DYNAMIC_SAMPLING参数值在缺乏统计信息时进 行动态统计信息收集。
6、执行查询
执行计划是SQL语句的执行方式,由查询优化器为语句设计的执行方式,交给执行器
去执行。在SQL命令行使用EXPLAIN可以打印出语句的执行计划 例如:
建表和建索引语句:
CREATE TABLE T1 (C1 INT,C2 CHAR);
CREATE TABLE T2 (D1 INT,D2 CHAR);
CREATE INDEX IDX T1 C1 ON T1(C1);
INSERT INTO T1 VALUES(1,‘A’);
INSERT INTO T1 VALUES(2,‘B’);
INSERT INTO T1 VALUES(3,‘C’);
INSERT INTO T1 VALUES(4,‘D’);
INSERT INTO T2 VALUES(1,‘A’);
INSERT INTO T2 VALUES(2,‘B’);
INSERT INTO T2 VALUES(5,‘C’);
INSERT INTO T2 VALUES(6,‘D’);
打印执行计划:
EXPLAIN SELECT A.C1+1,B.D2 FROM T1 A, T2 B WHERE A.C1 = B.D1;
执行计划如下:
1 #NSET2: [0,16,9]
2 #PRJT2: [0,16,9]; EXP NUM(2), IS ATOM(FALSE)
3 #NEST LOOP INDEX JOIN2: [0,16,9]
4 #CSCN2: [0,4,5] ;INDEX33555535(B)
5 #SSEK2: [0,4,0] ;SCAN TYPE(ASC), IDX T1 C1 (A),
SCAN RANGE[T2.D1,T2.D1]
这个执行计划看起来就像一棵树,执行过程为:控制流从上向下传递,数据流从下向上 传递。其中,类似[0,16,9]这样的三个数字,分别表示估算的操作符代价、处理的记录 行数和每行记录的字节数。同一层次中的操作符,如本例中的CSCN和SSEK由父节点NEST LOOP INDEX JOIN控制它们的执行顺序。
该计划的大致执行流程如下:
1)CSCN2:扫描T2表的聚集索引,数据传递给父节点索引连接;
2)NEST LOOP INDEX JOIN2:当左孩子有数据返回时取右侧数据;
3)SSEK:利用T2表当前的D1值作为二级索引IDX_T1_C1定位查找的KEY,返回 结果给父节点;
4)NEST LOOP INDEX JOIN2:如果右孩子有数据则将结果传递给父节点PRJT2,否则继续取左孩子的下一条记录;
5)PRJT2:进行表达式计算C1+1, D2;
6)NSET2:输出最后结果;
7)重复过程1) ~ 4)直至左侧CSCN2数据全部取完。
用户如果想了解更多关于操作符的知识,请查看动态视图V$SQL_NODE_NAME,手册 的附录4给出了常用操作符的说明。
为了提高查询效率,用户一般会在表中创建索引。查询中的条件列为索引列时,如果索 引扫描代价最小,优化器就会采用索引扫描。索引扫描有多种方式,例如,索引等值查询、 索引范围查询。如果查询列属于索引列的子集,则通过索引扫描就可以获得数据,否则,还 需要根据ROWID或者PK在聚集索引中定位记录。
7、查询计划重用
如果同一条语句执行频率较高,或者每次执行的语句仅仅是常量值不同,则可以考虑使 用计划重用机制。避免每次执行都需要优化器进行分析处理,可以直接从计划缓存中获取己 有的执行计划,减少了分析优化过程,提高执行率。
对于计划重用,达梦数据库提供了 INI参数USE_PLN_POOL来控制,当置为1时,会 启用计划重用。
8、结果集重用
执行计划的生成与优化是一个非常依赖CPU的操作,而执行一个查询获得结果集也是一 个非常消耗资源的操作。当系统连续执行两个完全相同的SQL语句,其执行计划和结果集很 有可能是相同的,如果重新生成和执行计划,会大大浪费系统资源。这时如果使用计划重用 和结果集重用,系统的响应速度可以大大提升。
结果集重用是基于计划重用的,如果查询的计划不能缓存,则其查询结果集必然不能缓 存。此外,当语句的游标属性为FORWARD ONLY时,默认查询不会生成结果集。而参数 BUILD_FORWARD_RS可以强制在此类查询中生成结果集,以便进行结果集重用。
可通过设置INI参数RS_CAN_CACHE来控制结果集重用。当置为0时表示手动模式 (MANUAL),在此模式下默认不缓存查询结果集,但是DBA可以通过语句提示等方法指示系 统对必要的查询结果集进行缓存;置为1时表示强制模式(FORCE),在此模式下默认缓存 所有可缓存结果集,但是DBA也可以通过新増的配置参数以及语句提示等方法取消某些不合 适的结果集缓存。
当RS_CAN_CACHE为1时,还可以通过设置INI参数RS_CACHE_TABLES和 RS_CACHE_MIN_TIME对缓存的结果集进行限制和过滤。RS_CACHE_TABLES指定可以缓 存结果集的基表清单,只有查询涉及的所有基表全部在参数指定范围内,此查询才会缓存结 果集。RS_CACHE_MIN_TIME则指定了缓存结果集的查询语句执行时间的下限,只有实际执 行时间不少于指定值的查询结果集才会缓存。
DBA 可以通过在 SQL 语句中设置 “RESULT_CACHE” 或 “NO_RESULT_CACHE” HINT 手动指示查询的结果集是否缓存。如:
select / *+ RESULT CACHE */ id, name from sysobjects;
或者
select / *+ NO_RESULT_CACHE */ id, name from sysobjects;
在语句中使用HINT指定结果集缓存的优先级要高于INI中相关参数的设置。
还可以使用系统过程SP_SET_PLN_RS_CACHE来强制设置指定计划结果集缓存的生效 及失效。这个系统过程对结果集缓存的指定高于其它所有结果集缓存的设置。
在以下情况下,DM不支持结果缓存:
1.必须是单纯的查询语句计划,PL脚本中包含查询语句也不能缓存结果集。
2.查询语句的计划本身必须是缓存的。
3.守护环境中的备机不支持结果集缓存。
4.MPP等集群环境下不支持结果集缓存(3、4两点限制都是因为无法精确控制基表 的数据更新时戳)。
5.查询语句中包含以下任意一项,其结果集都不能缓存:
1)包含临时表;
2)包含序列的CURVAL或NEXTVAL;
3)包含非确定的SQL函数或包方法(现有逻辑是不支持所有SQL函数或包方法);
4)包含RAND、SYSDATE等返回值实时变化的系统函数;
5)包含其它的一些实时要素。

你可能感兴趣的:(DM达梦数据库--查询优化)