数据库SQL执行流程和索引添加

您所在的位置:网站首页 oracle添加一个字段并加注释 数据库SQL执行流程和索引添加

数据库SQL执行流程和索引添加

2023-03-25 03:28| 来源: 网络整理| 查看: 265

以下内容来自腾讯工程师 fran

数据库的操作,无非就是增删改查。数据库的索引的添加对数据库的查询/更新性能有所提升,但也不是一成不变的,添加索引理论上会对增、删性能有影响,但是不同情况也会有差异。

1. 数据库语句的执行流程:

客户端:客户端/业务组件发送sql语句给mysql-server

查询缓存(只针对select语句):

缓存的数据结构是哈希表,以sql、数据库名和客户端协议等作为KEY去判断命中,Value为具体返回值,一旦命中则直接返回给客户端。缓存判断的是原始信息,而不是解析后的语句,所以任何空格、注释的不同都不会触发命中。当表的数据或表结构发生了变化,则缓存失效,即涉及INSERT、UPDATE、 DELETE、TRUNCATE、ALTER TABLE、DROP TABLE或DROP DATABASE会导致缓存数据失效,所以对表频繁进行更新或者删除或者插入的情况不用考虑缓存影响,此外SQL语句中不确定的函数或者语句都不会被缓存(注意:mysql8中缓存功能下线)。

解析处理优化:mysql对sql语句进行语句解析处理,区分是四种语句的哪种,并对语法合法性进行判断,对采用哪种索引进行查询性能更优作出判断,并排入执行计划。

执行器:对执行计划调用存储引擎API进行查询,将结果返回给客户端。

存储引擎:调用API对数据进行查询。当为update,delete和insert语句时:还要执行三个流程:redo log prepare——binlog——redo log commit:

1)首先引擎将更新的数据更新到内存和redolog中,告知执行器随时提交事物,此时redolog为prepare状态。

2)执行器收到引擎告知后生成binlog日志,并且调用接口提交事物,引擎将redolog的状态修改为commit,此时数据更新操作完成。

redolog:redolog属于物理日志,是Inno DB引擎的,物理上写入是顺序写入,减少寻址,提高IO效率,并且写入的方式是环状写入,即写完固定大小后就会触发刷盘操作,然后清除日志,继续接受redolog的写入。

binlog:binlog是mysql自带的逻辑日志,记录的是原始sql语句。

文件系统或块设备:文件系统块的页大小一般为8kb(4kb),跟底层存储性能相关,添加索引也是为了减少IO交互,提高性能。

2. 是否加索引判断

从以上数据库sql执行的全流程中可以看到sql执行的瓶颈点主要在客户端到mysqlserver、sql解析处理优化、存储引擎的选择、底层数据的存储方式(文件系统或块设备)这几点,本次主要讨论解析处理优化(索引的添加)这个环节。

首先确定几个问题:

首先大数据量,什么是大数据量?如何判断?有没有具体规格反馈到表里?可以找产品确认。确定客户端(业务组件里)给表下发的具体sql是什么?可以找开发确认或者拿源码确认。

索引对增删改的影响:

insert:insert除了要插数据在表中,还要维护索引(把值和叶子节点的指针更新,过程中有查询),表里有几个索引就要维护几个索引,所以有时候insert性能较差,可能是索引过多导致维护索引成本较高引起的,测试时需要注意。另外如果insert语句为copy表中某行数据的话(比如insert into table select* from table where *),也会用到索引,此时如果不加索引的话,insert性能反而会降低。

delete:与insert类似,删除一条数据也会同时把这条数据涉及的多个索引中的数据删除。但是删除如果跟where条件时会触发查询语句,如果查询上有索引时也会优化delete整体性能,所以还要具体看delete的sql语句是什么,例如一个表中,没有添加check_time的索引,用explain查看delete的执行过程:

需要遍历11w行,执行时间:

0.75s,添加了索引后:

explain发现整个delete过程中采用了索引,遍历的行数只有1行:

delete的时间大大减小。

update:只有当update中set的字段涉及到索引时,才需要维护索引,且update语句后跟where条件会触发查询,当触发查询上有索引时也会进一步优化update整体性能,所以加索引也会优化update语句,所以还要具体看update的sql语句是什么。

结论:添加索引后对增删改查的性能提升影响度依次是:

select>update>delete>=insert

索引添加的一般规律:

尽量添加跟sql语句强相关的复合索引,避免创建很多个独立的索引。比如where 后跟条件A and B and C,则创建一个索引包含ABC字段,而不是单独创建包含A、B、C的三条索引。(复合索引支持最左前缀集合)表里的数据类型越简单越小越好,比如整型好于字符串,用内置的时间和日期的数据类型好于直接用字符串来表示。另外如果用字符串形式存放日志数据也会带来比较大的开销,测试时需要注意此场景。频繁查询的语句一定要创建相关的索引。索引不要创建太多,否则会带来额外的索引维护开销(性能和空间)。唯一性太差的字段不适合创建索引,没有太大意义。没有出现在Where语句后的字段不应该用来创建索引。小数据量不适合创建索引(几十条或几千条)。

欢迎点赞分享,搜索关注【鹅厂架构师】公众号,一起探索更多业界领先产品技术。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3