SQL调优

为什么数据查询速度慢

  • 数据量大
  • 全表扫描
  • 运算
数据量大

        分表分库,以MySQL来说,底层索引使用的是B+Tree,单表数据量应该避免超过2000万,原因是当数据超过两千万的话,树的高度就为3了,影响查询效率。

全表扫描

        添加索引,以MySQL底层索引结构B+Tree来说,索引能够大大减少IO查询次数,可以避免全表扫描。

运算

        避免在SQL语句中进行运算,可以拿到程序中,在内存中进行计算操作。

        

分库分表

分库分表的场景

        1、高并发场景,会造成IO读写频繁,对数据库造成压力,导致读写缓慢甚至宕机。一般情况下单机不要超过2K并发。

        2、大数据量场景,第一、由于底层索引导致,数据量大会导致索引树十分庞大,以MySQL来说,底层索引使用的是B+Tree,单表数据量应该避免超过2000万,原因是当数据超过两千万的话,树的高度就为3了,影响查询效率;第二、innodb最大的存储限制为64TB。

        注意:不是出现上面情况就一定需要分库分表,比如优先应该考虑的是:缓存、读写分离、索引等。

分库分表方式
        垂直拆分

        就是将原表中的字段拆分成多个表,或者多个库上去。每个库表结构都不同,都包含着部分字段。 

        例:原USER表: id        name        age        phone        city        email

       拆分后:USER_BASE:id        name        age

                      USER_INFO:id        phone        city        email

        特点:

                1、每个表的结构都不一样

                2、拆分出的表关联起来就是全量数据

                3、拆分出的表主键是一样的

        水平拆分

        就是将原表中的数据按照一定的规律拆分到不同的表中。

        例:原USER表: id        name        age        phone        city        email

                                     1            张           18          185***       ***        *** 

                                     2            王           25          176***       ***        ***                

                                     3            赵           23          177***       ***        ***

       拆分后:

                USER_I:       id        name        age        phone        city        email

                                     1            张           18          185***       ***        ***           

                                     3            赵           23          177***       ***        ***

                USER_I:       id        name        age        phone        city        email

                                     2            王           25          176***       ***        ***     

        特点:

                1、拆分出的表机构都相同

                2、拆分出表数据的并集是全量数据

水平拆分具体策略

1、Range依据字段范围

  • 年份,USER_2024        USER_2025
  • 月份,USER_202404        USER_202405 
  • 日期,USER_20240425        USER_20240526
  • 主键ID,依据ID进行分区,比如1000万条数据,分为四个区,每个区限制存储数据250万条。

缺点:大部分的请求,访问的可能都是最新的数据,所以有可能绝大部分请求还是达到了最新的表、库上了。

2、依据某个字段Hash操作

        比如某用户编号8410216,用户表拆分成64张表,用户编号%64张表

        计算出该用户信息该存储在哪张表。

缺点:如果继续分表扩容的话,就需要做数据迁移,比如原先64张表,扩容到128张表时,就需要重新计算做迁移工作了。

数据迁移问题:如何不影响正常使用做数据迁移,数据迁移都会有一个迁移进度,可以根据迁移进度来判断去新表还是旧表中取数据。

3、List预定义:列表匹配List函数对编号进行分区,比如编号为101,105,108的存储在一个分区,相比于Range,List分区是固定的。

缺点:不易扩展。

如何实现分库分表

   分库分表组件:
  • cobar:属于proxy层方案,不支持读写分离、存储过程、跨库Join和分页等操作
  • TDDL:属于client层方案,不支持join、多表查询等语法,支持读写分离,使用不多,因为依赖淘宝的diamond配置管理。
  • sharding-jdbc:当当开源,属于client层方案,支持SQL语法较多,支持分库分表,读写分离。

分表后的问题

  • 分片事务一致性难以解决
  • 跨节Join性能差,逻辑复杂 
  • 数据多次扩展,难度、维护量大
  • 查询所有表集合
  • 分布式全局唯一id

索引

什么是索引?

        索引是一个数据结构,相当于字典中的目录,帮助快速查询数据,避免全表查询,同时也会占用磁盘空间来存储索引,并且数据被修改时也要对索引进行重构。

从应用维度来讲都什么什么索引?

  • 普通索引
  • 主键索引
  • 非空索引
  • 组合索引
  • 全文索引
  • 空间索引

从物理存储维度来讲都有什么索引?

  • 聚簇索引(索引与数据存储在一起- InnoDB)
  • 非聚簇索引(索引与数据分开存储- MyIsam)

从数据结构维度来讲都有什么索引?

  • hash索引(优:查询效率高,缺:无法范围查询)
  • B+Tree索引(优:可以范围查询,缺:相对来说等值查询较慢)

详细说说B+Tree结构

相比于B-Tree,B+Tree的每个非叶子节点可以包含更多的分支、叶子节点通过双向链表连接,顺序查询性能更高。

操作索引

  1. 创建表的同时创建索引
  2. 表创建之后创建索引
  3. 查看索引
  4. 删除索引
--创建表时创建索引
create table table_name(
    id int primary key auto_increment,
    phone varchar(4) not null,
    index index_name(phone) using hash
)engine innodb default character set utf8mb4;

-表创建后创建索引
create index index_name on table(column,column)

alter table table_name add index index_name(column)

-查看表中有哪些索引
show index from table;

-删除索引
drop index index_name on table(column,column)

如何查看是否应用索引

explain select column from table

查询等级排序

system >const(主键形式)>eq_ref >ref >range(范围查询)>index >All,一个好的语句至少要达到range级别,最好达到ref,要杜绝All的出现。

常见可能引起索引失效、查询效率低下的场景

  • 条件中存在隐式转换
  • Join字段编码不一致
  • 不等于判断条件
  • like左模糊查询
  • in范围查询
  • 查询条件中使用函数
  • 对索引列进行运算
  • 使用or连接条件
  • select *

为什么说要product中要杜绝使用select *

  1. 增加网络传输开销,虽然单个查询的消耗微乎其微,但架不住量大。
  2. 增加服务器内存压力,映射的实体类对象变大。
  3. 没有添加索引的字段会进行回表查询,影响效率。

什么是回表查询

        回表查询是数据库中一种常见的查询优化技术。当执行一个SQL查询时,如果查询语句无法直接从索引中获取所需的所有列,就需要进行回表查询。

  • 10
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值