一篇关于mysql迁移达梦后相关sql的优化记录
一、两边执行计划的对比
首先要看mysql那边的执行计划:
然后看达梦这边的执行计划:
那其实这里可以发现一个点,mysql是有索引合并(也就是index_merge)这样的方式去优化的,所以各个字段加了一个单索引也能有很好的性能。然而达梦数据库则没有这样的东西,这也造成了一个问题是为啥明明是同样的索引,同样的数据,同样的表,mysql运行时间只需要0.1秒,而在达梦中却需要十多秒甚至更久。
二、数据库参数调优的判断
一般数据库相关参数的话,达梦厂商来安装的时候会直接用软件扫描服务器后直接给一个最合适的配置,我这次暂时不动。不过这里也给出排查的方法:
查询缓冲池命中率,接近1则为最优。其中回收区 recycle命中率低是正常的,它只是临时中转站
SELECT
NAME AS “缓冲池名称”,
SUM(PAGE_SIZE) * SF_GET_PAGE_SIZE() / 1024 / 1024 AS “缓冲池大小(MB)”,
SUM(RAT_HIT) / COUNT(*) AS “命中率”
FROM
v$bufferpool
GROUP BY NAME;
一般normal区命中率在0.999以上都是非常优秀的,说明几乎都是在内存中查询回去了,那就不用管参数的问题。如果命中率很低的情况,那就需要调整一些参数了,比如以下几个参数(仅作为参考,和自己的服务器性能相关):
MEMORY_POOL = 204800 #Memory Pool Size In Megabyte
BUFFER = 614400 #Initial System Buffer Size In Megabytes
HJ_BUF_GLOBAL_SIZE = 82000 #maximum hash buffer size for all hash join in Megabytes
HJ_BUF_SIZE = 4096 #maximum hash buffer size for single hash join in Megabytes
三、索引优化
那这个时候其实就可以认定为,既然mysql自身的那些索引没有效果,那么就只能利用达梦本身的索引了,那其实最好的就是针对特别慢的查询做一个专门的复合索引。
复合索引的创建原则呢就是过滤性好的字段放前面,它会自动按照最左原则去查询,只需要查询where后的字段都包含在索引中即可。
比如针对这个查询:
主要看联表查的键以及where后面的部分,创建两个复合索引
CREATE OR REPLACE INDEX “FKGL0513”.“idx_kh_ydkh_composite” ON “FKGL0513”.“kh_ydkh”(“gddwbm” ASC,“cbqdbh” ASC,“yhbh” ASC,“yhztdm” ASC) STORAGE(ON “MAIN”, CLUSTERBTR) ;
CREATE OR REPLACE INDEX “FKGL0513”.“idx_fk_yhda_composite” ON “FKGL0513”.“fk_yhda”(“dqbm” ASC,“ffms” ASC,“fkms” ASC,“dazt” ASC,“yhbh” ASC) STORAGE(ON “MAIN”, CLUSTERBTR) ;
即可达成最优的查询效果
四、索引明明修改了,但是为啥没生效啊??我真的好崩溃!
创建完索引后,explain显示这样的效果:
可以发现它没有走刚刚建好的复合索引,而是继续使用了系统给的主键(即这个INDEX33589682),然后回表查询得出结果,为什么呢?
这时候需要用这个语句:
DBMS_STATS.GATHER_TABLE_STATS(‘用户名’,‘表名’,NULL,100,TRUE,‘FOR ALL COLUMNS SIZE AUTO’);
提取一下表的统计信息。这种情况是它认为表数据量不大,然后用了错误的执行计划(即主键查询+回表)。当数据量大了之后,就必须用复合索引才是最优。当刷新了这个数据后,就可以重新判断执行计划了。
ps:此处需要重新改一下sql的格式以触发新的执行计划,比如加个空格啊或者换个写法啊什么的
然后就能发现它走了下面这个执行计划:
此时再去查询,就能发现效率已经大大提升。
五、不改sql的格式如何刷新执行计划呢?毕竟我也不可能专门为了这个sql重新发布一个包吧!
select cache_item from v$cachepln where sqlstr like ‘%SQL语句的部分内容%’; 通过这个语句查询就可以得到关于执行计划的item信息,可以看作是执行计划的唯一ID。
然后将查出来的item带入这个语句执行:
call sp_clear_plan_cache(CACHE_ITEM);
相当于清空了旧的执行计划,这样再次查询的时候就会使用新的执行计划。
此时再查,发现耗时0.8秒,对比之前的十多秒算是巨大优化了,大功告成。
