首页 文章 正文 Mysql-索引优化 2024-07-02 1176阅读 0评论 一、插入数据优化 插入数据多条可以使用批量插入。 如果一次性需要插入大批量数据,使用insert语句插入性能较低,此时可以使用MySQL数据库提供的load指令进行插入。操作如下。 #客户端连接服务端时,加上参数--local-infile mysql --local-infile -u root -p #设置全局参数local_infile为1,开启从本地加载文件导入数据的开关 set global local infile=1; #执行load指令将准备好的数据,加载到表结构中 load data local infile '/root/sall.log' into table 'tb_user fields terminated by ',’ lines terminated by '\n' ; 说明:/root/sall.log需要导入数据文件路径 , tb_user表名 文件的数据格式为(数据之间以,分割,一行是一条数据) 查看是否支持 SELECT @@local_infile 二、主键优化 满足业务需求的情况下,尽量降低主键的长度, 插入数据时,尽量选择顺序插入, 选择使用AUTOINCREMENT自增主键尽量不要使用UUID做主键或者是其他自然主键,如身份证号。 页分裂(Page Splitting)是B树(或B+树)索引在插入数据时,遇到某个页已经满了,无法再插入新记录时,所采取的一种处理机制。页分裂的具体过程如下: 1 找到目标页:首先,找到需要插入新记录的页。 2 检查页的空间:检查该页是否有足够的空间来插入新记录。如果没有空间,就需要进行页分裂。 3 创建新页:在原页旁边创建一个新的页。 4 重新分配记录:将原页中的一部分记录移动到新页中。一般是将大约一半的记录移动到新页,以保持平衡。 5 更新指针:更新树结构中的指针,以反映页分裂后的新结构。 页分裂的主要目的是保持树的平衡,确保查询操作的效率。页分裂会导致数据库的写操作性能下降,因为它涉及到大量的I/O操作和树结构的调整。 页合并(Page Merging)是与页分裂相对应的一种操作。当B树(或B+树)索引中某些页的记录太少,低于一定的阈值时,数据库会将这些记录合并到相邻的页中,以提高空间利用率和查询性能。页合并通常在删除大量记录之后发生 页合并的过程 1 找到目标页:首先,找到记录数量低于阈值的页。 2 检查相邻页:检查相邻的页,看看是否有足够的空间来容纳目标页中的记录。 3 移动记录:将目标页中的记录移动到相邻页中。 4 释放目标页:将目标页释放或标记为可用空间。 5 更新指针:更新树结构中的指针,以反映页合并后的新结构。 MERGE_THRESHOLD:合并页的阈体,可以自己设置,在创建表或者创建索引时指定。 innodb_page_merge_threshold = 50 这里的 50 表示当一个页中的记录数量低于 50% 时,InnoDB 会尝试进行页合并 三、order by 优化 Using flesor:通过表的索引或全表扫描,读取满足条件的数据行,然后在排序缓冲区sonbufter中完成排序操作,所有不是通过索引直接返回排序结果的排序都叫 FileSort 排序。 Using index:通过有序索引顺序扫描直接返回有序数据,这种情况即为using index,不需要额外排序,操作效率高。 根据排序字段建立合适的索引,多字段排序时,也遵循最左前缀法则。 尽量使用覆盖索引。 多字段排序,一个升序一个降序,此时需要注意联合索引在创建时的规则(ASC/DESC)。 如果不可避免的出现filesort,大数据量排序时,可以适当增大排序缓冲区大小sort_buffer_size(默认256k)。 示例 #没有创建索引时,根据age,phone进行排序 explain select id,age,phone from tb_user order by age , phone; #创建索引 create index idx_user_age_phone_aa on tb_user(age,phone); #创建索引后,根据age,phone进行升序排序 explain select id,age,phone from tb_user order by age , phone; #创建索引后,根据age,phone进行降序排序 explain select id,age,phone from tb_user order by age desc , phone desc #根据age,phone进行降序一个升序,一个降序 explain select id,age,phone from tb_user order by age asc , phone desc; #创建索引create, index_idx_user_age_phone_ad on tb_user(age asc ,phone desc); #根据age,phone进行降序一个升序,一个降序 explain select id,age,phone from tb user order by age asc , phone desc; 四、group by优化 在分组操作时,可以通过索引来提高效率, 分组操作时,索引的使用也是满足最左前缀法则的。 示例 #执行分组操作,根据profession字段分组 explain select profession ,count(*) from tb_user group by profession ; #创建索引 Create index_idx_user_pro_age_sta on tb_user(profession , age , status); #执行分组操作,根据profession字段分组 explain select profession , count(*) from tb_user group by profession; #执行分组操作,根据profession字段分组 explain select profession ,count(") from tb_user group by profession, age; 五、limit 优化 一般分页查询时,通过创建覆盖索引 能够比较好地提高性能,可以通过覆盖索引加子查询形式进行优化。 explain select * from tb_sku t , (select id from tb_sku order by id limit 2000000,10) a where t.id = a.id; 六、count 优化 count(主键) InnoD8 引擎会遍历整张表,把每一行的 主键id 值都取出来,返回给服务层。服务层拿到主键后,直接按行进行累加(主键不可能为nul)。 count(字段) 没有not null约束:InnoD8 引擎会遍历整张表把每一行的字段值都取出来,返回给服务层,服务层判断是否为null,不为nul,计数累加。 有not nuul约束:InnoD8 引擎会遍历整张表把每一行的字段值都取出来,返回给服务层,直接按行进行累加。 count(1) InnoDB 引擎遍历整张表,但不取值。服务层对于返回的每一行,放一个数字“1”进去,直接按行进行累加。 count(*) InnoDB引擎并不会把全部字段取出来,而是专门做了优,不取值,服务层直接按行进行累加 按照效率排序的话,count(字段)<count(主键id)<count(1)≈ count(*),所以尽量使用 count(*)。 七、update 优化 InnoDB的行锁是针对索引加的锁,不是针对记录加的锁,并且该索引不能失效,否则会从行锁升级为表锁。 尽量根据主键或者索引字段进行数据更新 示例 建议 update student set no='2000100100'where id = 1; 不建议 update student set no='2000100105'where name ='韦一笑',
发表评论
还没有评论,来说两句吧...