数据库优化
执行计划
执行计划是SQL语句的执行方式,由查询优化器为语句设计的执行方式,交给执行器去执行。在SQL命令行使用EXPLAIN可以打印出语句的执行计划。
执行计划是由各类操作符组成的一颗树,也就是排序好的操作符的展现形式,从内到外依次执行。缩进越多的越先执行,同样缩进的上面的先执行,下面的后执行,上下的优先级高于内外。
例
explain
select employee_name,salary,department_name
from DMHR.EMPLOYEE,DMHR.DEPARTMENT
where department.department_id=employee.DEPARTMENT_ID;
这里的执行顺就是:CSN2àCSN2àHASH2 INNER JOINàPRJT2àNSET2
- 一个执行计划由若干个计划节点组成,如上面的CSN2、HASH2 INNER JOIN、PRJT2、NSET2
- 每个计划节点中包含操作符(CSCN2)和它的代价([0, 46, 52])等信息。
- 代价由一个三元组组成[代价,记录行数,字节数]。
- 代价的单位是毫秒,记录行数表示该计划节点输出的行数,字节数表示该计划节 点输出的字节数。
- 拿上面第三个计划节点举例:操作符是CSCN2即全表扫描,代价估算是0ms,扫描的记录行数是46行,输出字节数是52个。
执行计划操作符
NSET:收集结果集
说明:用于结果集收集的操作符, 一般是查询计划的顶层节点
PRJT:投影
说明:关系的"投影"(project)运算,用于选择表达式项的计算;广泛用于查询,排序,函数索引创建等。
SLCT:选择
说明:关系的"选择" 运算,用于查询条件的过滤。
AAGR:简单聚集
说明:用于没有group by的count,sum,age,max,min等聚集函数的计算。
FAGR:快速聚集
说明:用于没有过滤条件时从表或 索引快速获取 MAX/MIN/COUNT值,DM数据库是世界上单表不带过滤条件下取COUNT值最快的数据库。
HAGR:HASH分组聚集
说明:用于分组列没有索引只能走全表扫描的分组聚集,C2列没有创建索引。
SAGR:流分组聚集
说明:用于分组列是有序的情况下可以使用流分组聚集,C1上已经创建了索引,SAGR2性能优于HAGR2。
BLKUP:二次扫描
说明:先使用2级别索引定位,再根据表的主键、聚集索引、 rowid等信息定位数据行。
CSCN:全表扫描
说明:CSCN2是CLUSTER INDEX SCAN的缩写即通过聚集索引扫描全表,全表扫描是最简单的查询,如果没有选择谓词,或者没有索引可以利用,则系统一般只能做全表扫描。在一个高并发的系统中应尽量避免全表扫描。
SSEK、CSEK、SSCN:索引扫描
说明:
SSEK2是二级索引扫描即先扫描索引,再通过主键、聚集索引、ROWID等信息去扫描表;
CSEK2是聚集索引扫描只需要扫描索引,不需要扫描表;
SSCN是索引全扫描,不需要扫描表。
如果要了解更详细内容可以参考管理员手册的附录四。
SQL调优
查找慢SQL
在打开监控开关(ENABLE_MONITOR=1、MONITOR_TIME=1)后,可以通过查询动态视图V$LONG_EXEC_SQLS或V$SYSTEM_LONG_EXEC_SQLS来确定高负载的SQL语句。
前者显示最近1000条执行时间较长的SQL语句,后者显示服务器启动以来执行时间最长的20条SQL语句。
- select * from v$LONG_EXEC_SQLS;
- select * from v$SYSTEM_LONG_EXEC_SQLS;
也可以使用达梦自带的性能监视工具查看。
表连接
1)嵌套循环连接
NEST LOOP原理:
两层嵌套循环结构,有驱动表和被驱动表之分。 选定一张表作为驱动表,遍历驱动表中的每一行,根据连接条件去匹配第二 张表中的行。驱动表的行数就是循环的次数,这个很大程度影响了执行效率。
需注意的问题:
选择小表作为驱动表。统计信息尽量准确,保证优化器选对驱动表。
大量的随机读。如果没有索引,随机读很致命,每次循环只能读一块, 不能读多块。使用索引可以解决这个问题。
使用场景:
驱动表有很好的过滤条件。
表连接条件能使用索引。
结果集比较小。
2)哈希连接
hash join原理:
使用较小的Row source 作为Hash table和Bitmap, 而第二个row source被hashed,根据bitmap与第一个row source生成的hash table 相匹配,bitmap查找的速度极快。
hash join特点:
一般没索引或用不上索引时会使用该连接方式。
选择小的表(或row source)做hash表。
只适用等值连接中的情形。
由于hash连接比较消耗内存,如果系统有很多这种连接时,需调整以下3个参数:
HJ_BUF_GLOBAL_SIZE
HJ_BUF_SIZE
HJ_BLK_SIZE
开发有效的SQL语句
避免使用OR子句
避免使用困难的正则表达式
灵活使用伪表(SYSDUAL)
SELECT项避免'*'
避免功能相似的重复索引
使用COUNT(*)统计结果行数
使用EXPLAIN来查看执行计划
UNION和UNION ALL的选择
优化GROUP BY ... HAVING
使用优化器提示(HINT)
使用hint
总结:
关于SQL优化主要还是需要先分析系统当前哪些语句是性能影响最大的,一般是那些单个SQL执行慢且执行频率高的。
然后再结合执行计划去进行优化,优化大致思路为:
使用索引:选择合适的索引。
改写SQL:
将left join等价改为inner join;
避免隐式转换不走索引;
将过滤条件上拉,走索引;
用分析函数,减少表扫描。
…