文章目录

  • 概述
  • 1.数据准备
  • 步骤1:创建数据库和建表
  • 步骤2:设置参数
  • 步骤3:创建函数
  • 步骤4:创建存储过程
  • 步骤5:调用存储过程
  • 步骤6:删除某表上的索引
  • 2.索引失效案例
  • 2.1 全值匹配我最爱
  • 2.2 最佳左前缀法则
  • 2.3 主键插入顺序
  • 2.4 计算、函数、类型转换(自动或手动)导致索引失效
  • 2.5 类型转换导致索引失效
  • 2.6 范围条件右边的列索引失效(包含范围查询)
  • 2.7 不等于(!= 或者<>)索引失效
  • 2.8 is null可以使用索引,is not null无法使用索引
  • 2.9 like以通配符%开头索引失效
  • 2.10 OR 前后存在非索引的列,索引失效
  • 2.11 数据库和表的字符集统一使用utf8mb4
  • 2.12 小练习
  • 3.关联查询优化
  • 3.1 数据准备
  • 3.2 采用左外连接
  • 3.3 采用内连接
  • 3.4 join语句原理
  • 3.4.1驱动表和被驱动表
  • 3.4.2 simple Nest-Loop Join(简单嵌套循环连接)
  • 3.4.3 index Nest-Loop Join(索引嵌套循环连接)
  • 3.4.4 Block Nest-Loop Join(块嵌套循环连接)
  • 3.4.5 小结
  • 3.4.5 hash join
  • 4. 子查询优化
  • 5. 排序优化
  • 5.1 排序优化
  • 5.2 测试
  • 5.3 案例实战
  • 5.4 filesort算法:双路排序和单路排序
  • 6. GROUP BY优化
  • 7. 优化分页查询
  • 8. 优先考虑覆盖索引
  • 8.1 什么是覆盖索引?
  • 8.2 覆盖索引的利弊
  • 9. 如何给字符串添加索引
  • 9.2 前缀索引对覆盖索引的影响
  • 10. 索引下推
  • 10.1 索引下推概述
  • 10.2 ICP的开启、关闭
  • 10.3 ICP的使用条件
  • 10.4 使用前后对比
  • 11. 普通索引 vs 唯一索引
  • 12. 其它查询优化策略
  • 12.1 EXISTS 和 IN 的区分
  • 12.2 COUNT(*)与COUNT(具体字段)效率
  • 12.3 关于SELECT(*)
  • 12.4 LIMIT 1 对优化的影响
  • 12.5 多使用COMMIT
  • 13. 淘宝数据库,主键如何设计的?
  • 13.1 自增ID的问题
  • 13.2 业务字段做主键
  • 13.3 淘宝的主键设计
  • 13.4 推荐的主键设计


概述

mysql 参数 调优 mysql8调优_SQL

1.数据准备

步骤1:创建数据库和建表

学员表 插 50万 条, 班级表 插 1万 条。

CREATE DATABASE atguigudb2;

CREATE TABLE `class` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`className` VARCHAR(30) DEFAULT NULL,
`address` VARCHAR(40) DEFAULT NULL,
`monitor` INT NULL ,
PRIMARY KEY (`id`)
) ENGINE=INNODB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

CREATE TABLE `student` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`stuno` INT NOT NULL ,
`name` VARCHAR(20) DEFAULT NULL,
`age` INT(3) DEFAULT NULL,
`classId` INT(11) DEFAULT NULL,
PRIMARY KEY (`id`)
#CONSTRAINT `fk_class_id` FOREIGN KEY (`classId`) REFERENCES `t_class` (`id`)
) ENGINE=INNODB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

步骤2:设置参数

  • 命令开启:允许创建函数设置:
set global log_bin_trust_function_creators=1; # 不加global只是当前窗口有效。
show variables like '%log_bin_trust_function_creators%';

mysql 参数 调优 mysql8调优_数据库_02

步骤3:创建函数

保证每条数据都不同。

#随机产生字符串
DELIMITER //
CREATE FUNCTION rand_string(n INT) RETURNS VARCHAR(255)
BEGIN
DECLARE chars_str VARCHAR(100) DEFAULT
'abcdefghijklmnopqrstuvwxyzABCDEFJHIJKLMNOPQRSTUVWXYZ';
DECLARE return_str VARCHAR(255) DEFAULT '';
DECLARE i INT DEFAULT 0;
WHILE i < n DO
SET return_str =CONCAT(return_str,SUBSTRING(chars_str,FLOOR(1+RAND()*52),1));
SET i = i + 1;
END WHILE;
RETURN return_str;
END //
DELIMITER ;
#假如要删除
#drop function rand_string;

-- 随机产生班级编号
#用于随机产生多少到多少的编号
DELIMITER //
CREATE FUNCTION rand_num (from_num INT ,to_num INT) RETURNS INT(11)
BEGIN
DECLARE i INT DEFAULT 0;
SET i = FLOOR(from_num +RAND()*(to_num - from_num+1)) ;
RETURN i;
END //
DELIMITER ;
#假如要删除
#drop function rand_num;

步骤4:创建存储过程

#创建往stu表中插入数据的存储过程
DELIMITER //
CREATE PROCEDURE insert_stu( START INT , max_num INT )
BEGIN
DECLARE i INT DEFAULT 0;
SET autocommit = 0; #设置手动提交事务
REPEAT #循环
SET i = i + 1; #赋值
INSERT INTO student (stuno, name ,age ,classId ) VALUES
((START+i),rand_string(6),rand_num(1,50),rand_num(1,1000));
UNTIL i = max_num
END REPEAT;
COMMIT; #提交事务
END //
DELIMITER ;
#假如要删除
#drop PROCEDURE insert_stu;

创建往class表中插入数据的存储过程

#执行存储过程,往class表添加随机数据
DELIMITER //
CREATE PROCEDURE `insert_class`( max_num INT )
BEGIN
DECLARE i INT DEFAULT 0;
SET autocommit = 0;
REPEAT
SET i = i + 1;
INSERT INTO class ( classname,address,monitor ) VALUES
(rand_string(8),rand_string(10),rand_num(1,100000));
UNTIL i = max_num
END REPEAT;
COMMIT;
END //
DELIMITER ;
#假如要删除
#drop PROCEDURE insert_class;

步骤5:调用存储过程

  • class
#执行存储过程,往class表添加1万条数据
CALL insert_class(10000);
  • stu
#执行存储过程,往stu表添加50万条数据
CALL insert_stu(100000,500000);

步骤6:删除某表上的索引

  • 在这里插入代码片创建存储过程
DELIMITER //
CREATE PROCEDURE `proc_drop_index`(dbname VARCHAR(200),tablename VARCHAR(200))
BEGIN
DECLARE done INT DEFAULT 0;
DECLARE ct INT DEFAULT 0;
DECLARE _index VARCHAR(200) DEFAULT '';
DECLARE _cur CURSOR FOR SELECT index_name FROM
information_schema.STATISTICS WHERE table_schema=dbname AND table_name=tablename AND
seq_in_index=1 AND index_name <>'PRIMARY' ;
#每个游标必须使用不同的declare continue handler for not found set done=1来控制游标的结束
DECLARE CONTINUE HANDLER FOR NOT FOUND set done=2 ;
#若没有数据返回,程序继续,并将变量done设为2
OPEN _cur;
FETCH _cur INTO _index;
WHILE _index<>'' DO
SET @str = CONCAT("drop index " , _index , " on " , tablename );
PREPARE sql_str FROM @str ;
EXECUTE sql_str;
DEALLOCATE PREPARE sql_str;
SET _index='';
FETCH _cur INTO _index;
END WHILE;
CLOSE _cur;
END //
DELIMITER ;
  • 执行存储过程
CALL proc_drop_index("dbname","tablename");

2.索引失效案例

mysql 参数 调优 mysql8调优_数据库_03

2.1 全值匹配我最爱

系统中出现的sql语句

EXPLAIN SELECT SQL_NO_CACHE * FROM student WHERE age = 30;
EXPLAIN SELECT SQL_NO_CACHE * FROM student WHERE age = 30 AND classId = 4;
EXPLAIN SELECT SQL_NO_CACHE * FROM student WHERE age = 30 AND classId = 4 AND `name` = 'abcd';

建立索引前执行(关注时间)

-- (286ms) 不使用索引
SELECT SQL_NO_CACHE * FROM student WHERE age = 30 AND classId = 4 AND `name` = 'abcd'; 

-- (48ms) 使用age索引
SELECT SQL_NO_CACHE * FROM student WHERE age = 30 AND classId = 4 AND `name` = 'abcd'; 

-- (1ms) 使用age 和classId 索引
SELECT SQL_NO_CACHE * FROM student WHERE age = 30 AND classId = 4 AND `name` = 'abcd';

-- (1ms) 使用age 和classId 和name 索引
SELECT SQL_NO_CACHE * FROM student WHERE age = 30 AND classId = 4 AND `name` = 'abcd';

添加必要索引

CREATE INDEX idx_age ON student(age);
CREATE INDEX idx_age_classid ON student(age, classId);
CREATE INDEX idx_age_classid_name ON student(age, classId,`name`);

mysql 参数 调优 mysql8调优_SQL_04


mysql 参数 调优 mysql8调优_服务器_05


mysql 参数 调优 mysql8调优_mysql_06

2.2 最佳左前缀法则

拓展:Alibaba《Java开发手册》
索引文件具有 B-Tree 的最左前缀匹配特性,如果左边的值未确定,那么无法使用此索引。

EXPLAIN SELECT SQL_NO_CACHE * FROM student WHERE age = 30 AND NAME = 'abcd';
EXPLAIN SELECT SQL_NO_CACHE * FROM student WHERE classId = 4 AND NAME = 'abcd';
EXPLAIN SELECT SQL_NO_CACHE * FROM student WHERE classId = 4 AND age = 30 AND NAME = 'abcd';

-- 只有idx_age_classid_name 情况下执行以下语句 key_len == 5 , 只使用了 name 索引, classid没用到,name页没用到
EXPLAIN SELECT SQL_NO_CACHE * FROM student WHERE age = 30 AND NAME = 'abcd';

mysql 参数 调优 mysql8调优_服务器_07


mysql 参数 调优 mysql8调优_服务器_08


mysql 参数 调优 mysql8调优_服务器_09


mysql 参数 调优 mysql8调优_mysql_10

2.3 主键插入顺序

mysql 参数 调优 mysql8调优_数据库_11


可这个数据页已经满了,再插进来咋办呢?我们需要把当前 页面分裂 成两个页面,把本页中的一些记录移动到新创建的这个页中。页面分裂和记录移位意味着什么?意味着: 性能损耗 !所以如果我们想尽量避免这样无谓的性能损耗,最好让插入的记录的 主键值依次递增 ,这样就不会发生这样的性能损耗了。所以我们建议:让主键具有 AUTO_INCREMENT ,让存储引擎自己为表生成主键,而不是我们手动插入 ,

比如: person_info 表:

CREATE TABLE person_info(
id INT UNSIGNED NOT NULL AUTO_INCREMENT,
name VARCHAR(100) NOT NULL,
birthday DATE NOT NULL,
phone_number CHAR(11) NOT NULL,
country varchar(100) NOT NULL,
PRIMARY KEY (id),
KEY idx_name_birthday_phone_number (name(10), birthday, phone_number)
);

我们自定义的主键列 id 拥有 AUTO_INCREMENT 属性,在插入记录时存储引擎会自动为我们填入自增的主键值。这样的主键占用空间小,顺序写入,减少页分裂。

2.4 计算、函数、类型转换(自动或手动)导致索引失效

create index idx_name on student;
--此语句比下一条好,(能够使用上索引)
EXPLAIN SELECT SQL_NO_CACHE * FROM student WHERE student.name LIKE 'abc%';

-- 不能使用索引
EXPLAIN SELECT SQL_NO_CACHE * FROM student WHERE LEFT(student.name,3) = 'abc';

第二种:索引优化失效

  • type为“ALL”,表示没有使用到索引,查询时间为 3.62 秒,查询效率较之前低很多。

2.5 类型转换导致索引失效

下列哪个sql语句可以用到索引。(假设name字段上设置有索引)

# 未使用到索引
EXPLAIN SELECT SQL_NO_CACHE * FROM student WHERE name=123;
# 使用到索引
EXPLAIN SELECT SQL_NO_CACHE * FROM student WHERE name='123';

mysql 参数 调优 mysql8调优_数据库_12

2.6 范围条件右边的列索引失效(包含范围查询)

  • 注意:右边指的是建立索引的顺序的右边
ALTER TABLE student DROP INDEX idx_name;
ALTER TABLE student DROP INDEX idx_age;
ALTER TABLE student DROP INDEX idx_age_classid;
EXPLAIN SELECT SQL_NO_CACHE * FROM student
WHERE student.age=30 AND student.classId>20 AND student.name = 'abc' ;

mysql 参数 调优 mysql8调优_mysql_13

2.7 不等于(!= 或者<>)索引失效

2.8 is null可以使用索引,is not null无法使用索引

EXPLAIN SELECT SQL_NO_CACHE * FROM student WHERE age IS NULL;
EXPLAIN SELECT SQL_NO_CACHE * FROM student WHERE age IS NOT NULL;

mysql 参数 调优 mysql8调优_mysql_14

2.9 like以通配符%开头索引失效

拓展:Alibaba《Java开发手册》
【强制】页面搜索严禁左模糊或者全模糊,如果需要请走搜索引擎来解决。

2.10 OR 前后存在非索引的列,索引失效

or 前后的字段都建立索引

# 未使用到索引
EXPLAIN SELECT SQL_NO_CACHE * FROM student WHERE age = 10 OR classid = 100;
#使用到索引
EXPLAIN SELECT SQL_NO_CACHE * FROM student WHERE age = 10 OR name = 'Abel';

mysql 参数 调优 mysql8调优_mysql 参数 调优_15

2.11 数据库和表的字符集统一使用utf8mb4

统一使用utf8mb4( 5.5.3版本以上支持)兼容性更好,统一字符集可以避免由于字符集转换产生的乱码。不
同的 字符集 进行比较前需要进行 转换 会造成索引失效。

2.12 小练习

mysql 参数 调优 mysql8调优_mysql 参数 调优_16


mysql 参数 调优 mysql8调优_mysql 参数 调优_17

3.关联查询优化

3.1 数据准备

3.2 采用左外连接

= 左边驱动表, = 右边是被驱动表

-- 无索引情况
EXPLAIN SELECT SQL_NO_CACHE * FROM `type` LEFT JOIN book ON type.card = book.card;

-- 给book添加索引 log(n)
create index Y on book(card)
EXPLAIN SELECT SQL_NO_CACHE * FROM `type` LEFT JOIN book ON type.card = book.card;

-- 给type 加上索引
create index X on `type`(card)
EXPLAIN SELECT SQL_NO_CACHE * FROM `type` LEFT JOIN book ON type.card = book.card;

mysql 参数 调优 mysql8调优_mysql_18

3.3 采用内连接

drop index X on type;
drop index Y on book;(如果已经删除了可以不用再执行该操作)
EXPLAIN SELECT SQL_NO_CACHE * FROM type INNER JOIN book ON type.card=book.card;

ALTER TABLE book ADD INDEX Y ( card);
EXPLAIN SELECT SQL_NO_CACHE * FROM type INNER JOIN book ON type.card=book.card;

ALTER TABLE type ADD INDEX X (card);
EXPLAIN SELECT SQL_NO_CACHE * FROM type INNER JOIN book ON type.card=book.card;

DROP INDEX X ON `type`;
EXPLAIN SELECT SQL_NO_CACHE * FROM TYPE INNER JOIN book ON type.card=book.card

ALTER TABLE `type` ADD INDEX X (card);
EXPLAIN SELECT SQL_NO_CACHE * FROM `type` INNER JOIN book ON type.card=book.card;

换成 inner join(MySQL自动选择驱动表)

结论: 对于内连接来说,查询优化器决定驱动表和被驱动表 , 两个表都有索引, 小表驱动大表

mysql 参数 调优 mysql8调优_服务器_19


mysql 参数 调优 mysql8调优_mysql_20

mysql 参数 调优 mysql8调优_服务器_21


mysql 参数 调优 mysql8调优_数据库_22

3.4 join语句原理

mysql 参数 调优 mysql8调优_服务器_23

3.4.1驱动表和被驱动表

mysql 参数 调优 mysql8调优_mysql_24


mysql 参数 调优 mysql8调优_mysql 参数 调优_25

3.4.2 simple Nest-Loop Join(简单嵌套循环连接)

mysql 参数 调优 mysql8调优_数据库_26


mysql 参数 调优 mysql8调优_mysql 参数 调优_27

3.4.3 index Nest-Loop Join(索引嵌套循环连接)

mysql 参数 调优 mysql8调优_数据库_28


mysql 参数 调优 mysql8调优_数据库_29

3.4.4 Block Nest-Loop Join(块嵌套循环连接)

mysql 参数 调优 mysql8调优_数据库_30


mysql 参数 调优 mysql8调优_mysql_31


mysql 参数 调优 mysql8调优_服务器_32


mysql 参数 调优 mysql8调优_数据库_33

3.4.5 小结

总结3:什么叫作“小表”?

在决定哪个表做驱动表的时候,应该是两个表按照各自的条件过滤,过滤完成之后,计算参与join的各个字段的总数据量,数据量小的那个表,就是“小表”,应该作为驱动表。

mysql 参数 调优 mysql8调优_SQL_34

3.4.5 hash join

mysql 参数 调优 mysql8调优_mysql 参数 调优_35


mysql 参数 调优 mysql8调优_SQL_36

4. 子查询优化

mysql 参数 调优 mysql8调优_SQL_37

5. 排序优化

5.1 排序优化

问题:在 WHERE 条件字段上加索引,但是为什么在 ORDER BY 字段上还要加索引呢?
优化建议:

  1. SQL 中,可以在 WHERE 子句和 ORDER BY 子句中使用索引,目的是在 WHERE 子句中 避免全表扫描 ,在 ORDER BY 子句 避免使用 FileSort 排序 。当然,某些情况下全表扫描,或者 FileSort 排序不一定比索引慢。但总的来说,我们还是要避免,以提高查询效率。
  2. 尽量使用 Index 完成 ORDER BY 排序。如果 WHERE 和 ORDER BY 后面是相同的列就使用单索引列;如果不同就使用联合索引。
  3. 无法使用 Index 时,需要对 FileSort 方式进行调优
INDEX a_b_c(a,b,c)
order by 能使用索引最左前缀
- ORDER BY a
- ORDER BY a,b
- ORDER BY a,b,c
- ORDER BY a DESC,b DESC,c DESC
如果WHERE使用索引的最左前缀定义为常量,则order by 能使用索引
- WHERE a = const ORDER BY b,c
- WHERE a = const AND b = const ORDER BY c
- WHERE a = const ORDER BY b,c
- WHERE a = const AND b > const ORDER BY b,c
不能使用索引进行排序
- ORDER BY a ASC,b DESC,c DESC /* 排序不一致 */
- WHERE g = const ORDER BY b,c /*丢失a索引*/
- WHERE a = const ORDER BY c /*丢失b索引*/
- WHERE a = const ORDER BY a,d /*d不是索引的一部分*/
- WHERE a in (...) ORDER BY b,c /*对于排序来说,多个相等条件也是范围查询*/
-

5.2 测试

ORDER BY子句,尽量使用Index方式排序,避免使用FileSort方式排序。
执行案例前先清除student上的索引,只留主键:

CALL proc_drop_index('atguigudb2','student');
CALL proc_drop_index('atguigudb2','calss');

SHOW INDEX FROM student;
SHOW INDEX FROM class;

mysql 参数 调优 mysql8调优_数据库_38


mysql 参数 调优 mysql8调优_mysql 参数 调优_39


mysql 参数 调优 mysql8调优_SQL_40


mysql 参数 调优 mysql8调优_服务器_41


mysql 参数 调优 mysql8调优_服务器_42


mysql 参数 调优 mysql8调优_SQL_43


mysql 参数 调优 mysql8调优_服务器_44


mysql 参数 调优 mysql8调优_SQL_45


mysql 参数 调优 mysql8调优_SQL_46

5.3 案例实战

场景:查询年龄为30岁的,且学生编号小于101000的学生,按用户名称排序

EXPLAIN SELECT SQL_NO_CACHE * FROM student WHERE age = 30 AND stuno <101000 ORDER BY NAME ;

mysql 参数 调优 mysql8调优_mysql_47


mysql 参数 调优 mysql8调优_数据库_48


mysql 参数 调优 mysql8调优_数据库_49


mysql 参数 调优 mysql8调优_mysql 参数 调优_50

结论:

  1. 两个索引同时存在,mysql自动选择最优的方案。(对于这个例子,mysql选择 idx_age_stuno_name)。但是, 随着数据量的变化,选择的索引也会随之变化的 。
  2. 当【范围条件】和【group by 或者 order by】的字段出现二选一时,优先观察条件字段的过 滤数量,如果过滤的数据足够多,而需要排序的数据并不多时,优先把索引放在范围字段 上。反之,亦然。

答案: 可行

mysql 参数 调优 mysql8调优_SQL_51

5.4 filesort算法:双路排序和单路排序

mysql 参数 调优 mysql8调优_SQL_52


mysql 参数 调优 mysql8调优_mysql_53


mysql 参数 调优 mysql8调优_数据库_54


mysql 参数 调优 mysql8调优_mysql_55

6. GROUP BY优化

  • group by 使用索引的原则几乎跟order by一致 ,group by 即使没有过滤条件用到索引,也可以直接使用索引。
  • group by 先排序再分组,遵照索引建的最佳左前缀法则
  • 当无法使用索引列,增大 max_length_for_sort_data 和 sort_buffer_size 参数的设置
  • where效率高于having,能写在where限定的条件就不要写在having中了
  • 减少使用order by,和业务沟通能不排序就不排序,或将排序放到程序端去做。Order by、group by、distinct这些语句较为耗费CPU,数据库的CPU资源是极其宝贵的。
  • 包含了order by、group by、distinct这些查询的语句,where条件过滤出来的结果集请保持在1000行以内,否则SQL会很慢。

7. 优化分页查询

mysql 参数 调优 mysql8调优_SQL_56


mysql 参数 调优 mysql8调优_mysql_57

8. 优先考虑覆盖索引

8.1 什么是覆盖索引?

select 的字段已经存在与索引中, 不需要回表操作情况下会使用索引,称为覆盖索引

  • 理解方式一:索引是高效找到行的一个方法,但是一般数据库也能使用索引找到一个列的数据,因此它不必读取整个行。毕竟索引叶子节点存储了它们索引的数据;当能通过读取索引就可以得到想要的数据,那就不需要读取行了。一个索引包含了满足查询结果的数据就叫做覆盖索引。
  • 理解方式二:非聚簇复合索引的一种形式,它包括在查询里的SELECT、JOIN和WHERE子句用到的所有列(即建索引的字段正好是覆盖查询条件中所涉及的字段)。
  • 简单说就是, 索引列+主键 包含 SELECT 到 FROM之间查询的列 。

8.2 覆盖索引的利弊

mysql 参数 调优 mysql8调优_服务器_58

9. 如何给字符串添加索引

mysql 参数 调优 mysql8调优_服务器_59


mysql 参数 调优 mysql8调优_SQL_60

9.2 前缀索引对覆盖索引的影响

结论:
使用前缀索引就用不上覆盖索引对查询性能的优化了,这也是你在选择是否使用前缀索引时需要考 虑的一个因素。

10. 索引下推

icp (索引下推)减少回表次数,提升查询效率

10.1 索引下推概述

mysql 参数 调优 mysql8调优_mysql_61


mysql 参数 调优 mysql8调优_mysql 参数 调优_62

10.2 ICP的开启、关闭

mysql 参数 调优 mysql8调优_mysql_63

10.3 ICP的使用条件

mysql 参数 调优 mysql8调优_mysql 参数 调优_64

10.4 使用前后对比

mysql 参数 调优 mysql8调优_SQL_65


mysql 参数 调优 mysql8调优_mysql 参数 调优_66


mysql 参数 调优 mysql8调优_数据库_67


mysql 参数 调优 mysql8调优_mysql_68


mysql 参数 调优 mysql8调优_服务器_69

11. 普通索引 vs 唯一索引

mysql 参数 调优 mysql8调优_数据库_70


mysql 参数 调优 mysql8调优_mysql 参数 调优_71

12. 其它查询优化策略

12.1 EXISTS 和 IN 的区分

mysql 参数 调优 mysql8调优_服务器_72


mysql 参数 调优 mysql8调优_mysql 参数 调优_73

12.2 COUNT(*)与COUNT(具体字段)效率

mysql 参数 调优 mysql8调优_SQL_74

12.3 关于SELECT(*)

在表查询中,建议明确字段,不要使用 * 作为查询的字段列表,推荐使用SELECT <字段列表> 查询。原
因:
① MySQL 在解析的过程中,会通过 查询数据字典 将"*"按序转换成所有列名,这会大大的耗费资源和时
间。
② 无法使用 覆盖索引

12.4 LIMIT 1 对优化的影响

  • 针对的是会扫描全表的 SQL 语句,如果你可以确定结果集只有一条,那么加上 LIMIT 1 的时候,当找到一条结果的时候就不会继续扫描了,这样会加快查询速度。
  • 如果数据表已经对字段建立了唯一索引,那么可以通过索引进行查询,不会全表扫描的话,就不需要加上 LIMIT 1 了。

12.5 多使用COMMIT

mysql 参数 调优 mysql8调优_服务器_75

13. 淘宝数据库,主键如何设计的?

mysql 参数 调优 mysql8调优_数据库_76

13.1 自增ID的问题

mysql 参数 调优 mysql8调优_mysql_77

13.2 业务字段做主键

mysql 参数 调优 mysql8调优_服务器_78


mysql 参数 调优 mysql8调优_mysql 参数 调优_79


mysql 参数 调优 mysql8调优_mysql 参数 调优_80


mysql 参数 调优 mysql8调优_数据库_81

13.3 淘宝的主键设计

mysql 参数 调优 mysql8调优_mysql_82


mysql 参数 调优 mysql8调优_mysql 参数 调优_83

13.4 推荐的主键设计

mysql 参数 调优 mysql8调优_mysql_84


mysql 参数 调优 mysql8调优_服务器_85


mysql 参数 调优 mysql8调优_数据库_86


mysql 参数 调优 mysql8调优_服务器_87