高性能 Mysql 调优

版权声明:转载请注明转载地址。 https://blog.csdn.net/qq_36144187/article/details/83928451

Class 1:(表达优化与列类型选择
1.定长与变长分离
核心且常用字段,宜建成定长,放在一张表。
而varchar,test这种变长字段,适合单一放一张表,用主键与核心表关联起来。

2.常用字段和不常用字段分离

3.在一对多需要关联统计的字段上添加冗余字段

 

Class 2:(列选择原则)
1.字段类型优先级:
整型>date,time>enum,char>varchar>blob(无法使用内存零时表),text (整形>char 不需要考虑字符集,和校对集 例:a B c D 比较大小)
以性别utf8为例:
enum('男‘,‘女’);内部转成数字来存,多了一个转换过程
char(1);,3个字节长度
tinyint();定长一个字节

2.够用就行,不要慷慨
大的字段浪费内存影响速度(Varchar(10)比Varchar(300)查询内容占用内存更小)

3.尽量避免使用null
NULL不利于索引,要用特殊的字节来标注
在磁盘上占的空间其实更大
where 列名=null
where 列名!=null 都查不到值
where 列名 is null 或 is not null才可以查询

Enum列的说明:
1.在内部用整型储存(多一个转化的过程)
2.enum列与enum列相关联速度最快
3.比(var)char弱在碰到与char关联时要花时间
4.优势在于当char非常长时,enum仍然是整型固定长度。当查询的数据量越大,enum的优势越明显

Class 3:

索引优化策略
btree索引:(innodb)将索引值按一定的算法,存入一个树形的数据结构中(二叉树),每次查询都是从树的入口root开始,依次遍历node,获取leaf。这是MySQL里默认和最常用的索引类型。(btree就是二叉树在磁盘的数据结构上的优化,根据磁盘块大小才有多叉而不是用二叉)
hash索引:
在memory表(内存引擎)里使用。理论查询时间复杂度为O(1)
缺点:
1.hash函数计算后的结果是随机的,如果是在磁盘上放置数据(磁盘上会有很多空洞)。
2.无法对范围查询进行优化。
3.无法利用前缀索引(hello 和 hello world)。
4.排序无法优化。
5.必须回行(索引和数据不在同一个文件内)。通过索引拿到数据位置必须回到表中取数据。

总结:(memory表)HASH索引可以一次定位,不需要像树形索引那样逐层查找,因此具有极高的效率。但是,这种高效是有条件的,即只在“=”和“in”条件下高效,对于范围查询、排序及组合索引仍然效率不高。

Class 4:

Btree索引的常见误区:

  1. 索引是相互独立的(where cat_id=3 and price > 100  的情况下只能使用一个索引,原理根据Btree数据结构可知。)

  2. 在实际应用中,使用的是联合索引(注意:和顺序有关或左前缀索引)

例:index(a,b,c)

Where  a=3 and b>4 (a,b同时起作用)

Where  a=3 and c>4 (a起作用 ,c不起作用)

Where  b=3 and c>4 (b,c同时不起作用)

Where  a>3 and b=4 (a起作用,b不起作用)

 

原理:根据Btree数据结构,另外排序顺序形似字符串排序。

  1. Btree索引同时能提高排序速度。

例:where c1=x and c4=x group by c3,c2

where c1=x and c4=x order by c3,c2

Class 5:

验证索引是否被使用:

Explain命令

例:explain select * from t4 where c1=3 and c2=4 and c4>5 and c3=2 \G

打印结果中的key_len =4 表示使用了4个 索引(是索引的长度不是数量,c1 长度为1) 如果值为null,代表该条指令没使用相关索引。

Class 6:(聚簇索引与非聚簇索引)

Myisam:数据和索引为两个单独的文件,索引指向数据在磁盘上的位置,为非聚簇索引。

Innodb:在主键索引文件上,直接存放该行数据,次索引指向主键引用,再使用主键找数据,为聚簇索引。(在某些情况下(表中有特长的数据列),使用次索引索引数据更快)

优势:数据少,不用回行。

劣势:当主键没有规律的时候,乱序插入会造成多次页分裂。

(形似于链表插入,和树插入)

Class 7:(索引覆盖)

在非聚簇索引中,所查询的数据就在索引文件中,即可不用回行。

例:create table t99(

Id int,

Name char(10),

Intro varchar(20),

Index inm(id,name)

)中

语句一:Select name from t99 where....

语句二:Select name,intro from t99 where....

在这两个语句中,语句一使用了索引覆盖。Explain命令中的Extra行显示

Using index

Class 8:(索引的合理设计)

  1. 查询频繁

  2. 区分度高:

例:男/女 不需要加。(一般情况下,达到0.1以上即可)

  1. 长度小的字段:

字段比较长,可以使用前几个字节建立索引

例:所有词组表,用第一个汉子做索引。

域名表,可以采用倒序之后的,前几个字节。

或者采用伪哈希技巧,CRC(域名)做索引。

  1. 尽量能覆盖常查询字段

  2. 列的查询顺序

根据不同的业务情况,使用冗余索引。(注意,有的索引有包含关系)

 

  1. Optimize table 清除索引碎片,表碎片。、

Class 9:(sql语句优化)

  1. sql语句时间花费

  1. 等待时间

  2. 执行时间(两个时间相关系)

  1. 取出数据

  2. 查找(按照索引)

  1. 查询的快:联合索引的顺序,区分度,长度

  2. 取得快:索引覆盖

  3. 传输的少:更少的行列

 

方法:切分查询

      例:插入一万行数据,改成1000行插十次。

      例:三表联查,改成两个两表联查(左连接多次,会有很多冗余数据)

 

Class 10:(explain详解)

1.id(查询执行的顺序)

2. select_type(查询中每个select子句的类型(简单OR复杂))

a. SIMPLE:查询中不包含子查询或者UNION
b. 查询中若包含任何复杂的子部分,最外层查询则被标记为:PRIMARY
c. 在SELECT或WHERE列表中包含了子查询,该子查询被标记为:SUBQUERY
d. 在FROM列表中包含的子查询被标记为:DERIVED(衍生)用来表示包含在from子句中的子查询的select,mysql会递归执行并将结果放到一个临时表中。服务器内部称 为"派生表",因为该临时表是从子查询中派生出来的
e. 若第二个SELECT出现在UNION之后,则被标记为UNION;若UNION包含在FROM子句的子查询中,外层SELECT将被标记为:DERIVED
f. 从UNION表获取结果的SELECT被标记为:UNION RESULT

      

   

3.Type

ALL, index,  range, ref, eq_ref, const, system, NULL

从左到右,性能从最差到最好

 

a.ALL:Full Table Scan, MySQL将遍历全表以找到匹配的行

b. index:Full Index Scan,index与ALL区别为index类型只遍历索引树

c.range:索引范围扫描,对索引的扫描开始于某一点,返回匹配值域的行。显而易见的索引范围扫描是带有between或者where子句里带有<, >查询。当mysql使用索引去查找一系列值时,例如IN()和OR列表,也会显示range(范围扫描),当然性能上面是有差异的。

d. ref:使用非唯一索引扫描或者唯一索引的前缀扫描,返回匹配某个单独值的记录行

     e. eq_ref:类似ref,区别就在使用的索引是唯一索引,对于每个索引键值,表中只有一条记录匹配,简单来说,就是多表连接中使用primary key或者 unique key作为关联条件

    f. const、system:当MySQL对查询某部分进行优化,并转换为一个常量时,使用这些类型访问。如将主键置于where列表中,MySQL就能将该查询转换为一个常量

    g. NULL:MySQL在优化过程中分解语句,执行时甚至不用访问表或索引,例如从一个索引列里选取最小值可以通过单独索引查找完成。

4. possible_keys

    指出MySQL能使用哪个索引在表中找到记录,查询涉及到的字段上若存在索引,则该索引将被列出,但不一定被查询使用

 

5. key

    显示MySQL在查询中实际使用的索引,若没有使用索引,显示为NULL

6. key_len

表示索引中使用的字节数,可通过该列计算查询中使用的索引的长度(key_len显示的值为索引字段的最大可能长度,并非实际使用长度,即key_len是根据表定义计算而得,不是通过表内检索出的)

7. ref

表示上述表的连接匹配条件,即哪些列或常量被用于查找索引列上的值

8. rows

表示MySQL根据表统计信息及索引选用情况,估算的找到所需的记录所需要读取的行数

9. Extra

包含不适合在其他列中显示但十分重要的额外信息

a. Using index

该值表示相应的select操作中使用了覆盖索引(Covering Index)

b. Using where

表示mysql服务器将在存储引擎检索行后再进行过滤。许多where条件里涉及索引中的列,当(并且如果)它读取索引时,就能被存储引擎检验,因此不是所有带where字句的查询都会显示"Using where"。有时"Using where"的出现就是一个暗示:查询可受益与不同的索引。

 

c. Using temporary

表示MySQL需要使用临时表来存储结果集,常见于排序和分组查询

 

d. Using filesort

MySQL中无法利用索引完成的排序操作称为“文件排序”

 

e. Using join buffer

改值强调了在获取连接条件时没有使用索引,并且需要连接缓冲区来存储中间结果。如果出现了这个值,那应该注意,根据查询的具体情况可能需要添加索引来改进能。

f. Impossible where
这个值强调了where语句会导致没有符合条件的行。

g. Select tables optimized away
这个值意味着仅通过使用索引,优化器可能仅从聚合函数结果中返回一行.

h. Index merges
当MySQL 决定要在一个给定的表上使用超过一个索引的时候,就会出现以下格式中的一个,详细说明使用的索引以及合并的类型。
Using sort_union(...)
Using union(...)
Using intersect(...)

 

EXPALIN只能解释SELECT操作,其他操作要重写为SELECT后查看执行计划。

 

Class 11:

1.in exist陷阱

Select * from table_a where id_a in(Select id_a from table_b where id_b = 6)

等效于exist 也就是  Select * from table_b where id_b = 6 and id_a=?

(id_a,id_b有索引)

所以反而是外面 用不上key,内层可以用上key。

2.union

MySQL UNION 操作符用于连接两个以上的 SELECT 语句的结果组合到一个结果集合中。多个 SELECT 语句会删除重复的数据。

1.会产生临时表。

2.尽量字表where条件精确,临时表变小。

3.尽量使用union all,可以避免查重,查重就要排序。

3.Limit

Limit offset,N 实际将会取offset+N条记录。Offset越大,实用效率越低。

 

1.业务解决(百度):回避大offset,只能70页左右。

2.使用条件查询,比如limit 500000,N  改成where id>500000 limit N。改用逻辑删除。

3.索引覆盖+加延迟索引:

   Select * from table

        Inner join

        (select id from table limit 500000,N)as tmp;

        On table.id=tmp.id

 

感谢:

     本学习笔记来自于网易云课堂  

       高性能Mysql :https://study.163.com/course/courseMain.htm?courseId=1003746011

       部分内容引用自 https://www.cnblogs.com/gomysql/p/3720123.html

 

 

猜你喜欢

转载自blog.csdn.net/qq_36144187/article/details/83928451