SQL优化
插入数据
- 批量插入
- 插入多条数据时,执行批量插入,但批量插入也不建议插入超过1k条
- 几百万数据时,多次批量插入
INSERT INTO table_name VALUES (..) (..) (..) ...;
- 手动事务提交
- 默认每一条DML语句都会开启\提交一次事务
- 手动开启事务,将多次插入进行一次提交
START TRANSACTION;
INSERT ..
INSERT ..
...
COMMIT;
- 主键顺序插入
- load
- 将本地磁盘文件的数据直接加载到数据库中,常用于万级、百万级数据
主键优化
- 在InnoDB存储引擎中,表数据是根据主键顺序组织存放的,称为索引组织表(IOT index organized tabel)
- 尽量减少页分裂、增多页合并 -- 尽量按序插入
- 应尽量降低主键的长度,因为二级索引的叶子节点存放主键的值
- 插入数据时,应尽量选择主键顺序插入,如选择使用 AUTO_INCREMENT 自增主键
- 尽量不要使用UUID做主键,或其他自然主键,如身份证号,会乱序插入,且长度过长
ORDER BY 排序优化
- Using filesort:通过表的所有或全表扫描,读取满足条件的数据行,然后在排序缓存区 sort buffer 中完成排序,所有不是通过索引直接返回排序结果的排序都叫做 FileSort 排序
- Using index:通过有序所有顺序扫描直接返回有序数据,不需要额外排序,操作效率高
- 尽量使用 Using index => 对有索引的字段进行与其索引相同顺序的排序
- 根据排序字段建立合适的索引,多字段排序时,也遵循最左前缀法则
- 尽量使用覆盖索引
- 多字段排序,一个升序一个降序,此时需要注意联合索引在创建时的规则 (ASC\DESC)
- 如果不可避免的出现FileSort,大量数据排序时,可以适当增大排序缓冲区大小(默认为256k)
GROUP BY 分组优化
- 可以通过索引提高效率
- 分组操作时,索引的使用也是满足最左前缀法则
LIMIT 分页优化
- 当执行 LIMIT 200_0000, 10时,此时 MySQL 需要排序前 200_0010条记录,仅仅返回 200_0000 ~ 200_0010 的记录,其他记录丢弃,查询排序代价大,性价比低
- 可以先查询数据的主键,在与查询到的主键数据进行多表联查,返回完整记录
COUNT 求和优化
- 在MyISAM引擎中,表的总行数被存储在磁盘中,因此执行 COUNT(*) 的时候会直接返回这个数,效率很高
- InnoDB引擎执行 COUNT(*) 时,需要吧数据一行行得读取,再进行累计计数
- 优化思路:自己计数存储数据量 。。。
- COUNT 的主要用法:COUNT( * ) , COUNT( 主键 ) , COUNT( 字段 ) , COUNT( 1 )
- **COUNT( 主键 ) **
- InnoDB 引擎会遍历整张表,将 主键id 值都取出来,返回给服务层,直接按行进行累加,主键不为 null ,因此不用判断值是否为 null
- COUNT( 字段 )
- 如果没有 NOT NULL 约束,InnoDB 引擎会遍历整张表,将每一行的字段值都取出来,返回给服务层,服务层判断是否为 NULL,不为 NULL,计数累加
- 有 NOT NULL 约束,InnoDB 引擎会遍历整张表,将每一行的字段值都取出来,返回给服务层,直接按行进行累加
- COUNT ( 1 )
- InnoDB 引擎会遍历整张表,但不取值,服务层对于返回的每一行,放一个数字 1 进去,直接按行进行累加
- **COUNT( * ) **
- InnoDB 引擎并不会把全部字段取出,而是专门做了优化,不取值,服务层直接按行累加
- **效率:COUNT( * ) = COUNT ( 1 ) ** > 其他
UPDATE 更新优化
- Kakfa 避免行锁升级为表锁 ???