MySql 数据查询优化

1. MySQL索引类型:

mysql的索引有5种:主键索引、普通索引、唯一索引、全文索引、聚合索引(多列索引)。
索引是一种特殊的文件,它们包含着对所有记录的引用指针。索引可以极大地提高数据查询速度,但是会降低插入删除更新表的速度,因为在执行这些操作是,还要操作索引文件用来维护

1)主键索引:主键索引是加在主键上的索引,设置主键(primary key)的时候,mysql会自动创建主键索引;
2)普通索引:创建在非主键列上的索引;
3)唯一索引:不允许两行具有相同的索引值
4)全文索引:是一种基于分词创建的索引,一般会涉及到搜索引擎的使用,参见《Laravel 中使用 sphinx 搜索引擎》
3)聚合索引:创建在多列上的索引。

主键索引和唯一索引的区别
(1) 对于主键数据库会自动建立唯一索引,使用关键字 PRIMARY KEY 来创建;
(2) 一个表最多只能创建一个主键,但可以创建多个唯一索引;
(3) 主键不一定只包含一个字段(可是多个字段的组合);
(4) 主键不可为空,唯一索引可为空;
(5) 主键索引一定是唯一索引, 唯一索引不是主键索引
(6) 主键可以被其他表引用为外键, 防止数据不一致,而唯一索引不能;

2. 索引的语法:

索引的遵循原则
1、最左侧原则,表的最左侧的一列,往往数据不会发生改变,不影响其他列的数据;
2、命名短小原则,索引命名过长会使索引文件变大,损耗内存。

查看某张表的索引:SHOW INDEX FROM 表名;
创建普通索引:ALTER TABLE 表名 ADD INDEX 索引名 (加索引的列)
创建聚合索引:ALTER TABLE 表名 ADD INDEX 索引名 (加索引的列1,加索引的列2)
删除某张表的索引:DROP INDEX 索引名 ON 表名;

或者直接在 Navicat Premium 工具中直接界面操作


11.png

3. EXPLAIN 分析SQL执行的状态

EXPLAIN 列的解释

table            显示这一行的数据是关于哪张表的

type             这是重要的列,显示连接使用了何种类型。从最好到最差的连接类型为const、eq_ref、ref、range、index、ALL

possible_keys    显示可能应用在这张表中的索引。如果为空,没有可能的索引。可以为相关的域从WHERE语句中选择一个合适的语句

key              实际使用的索引。如果为NULL,则没有使用索引。

key_len          使用的索引的长度。在不损失精确性的情况下,长度越短越好

ref              显示索引的哪一列被使用了,如果可能的话,是一个常数

rows             MYSQL认为必须检查的用来返回请求数据的行数

Extra            关于MYSQL如何解析查询的额外信息。

type字段值含义

const      表中的一个记录的最大值能够匹配这个查询(索引可以是主键或惟一索引)。因为只有一行,这个值实际就是常数,
           因为MYSQL先读这个值然后把它当做常数来对待

eq_ref     连接中,MYSQL在查询时,从前面的表中,对每一个记录的联合都从表中读取一个记录,它在查询使用了索引为主键或惟一键的全部时使用

ref        这个连接类型只有在查询使用了不是惟一或主键的键或者是这些类型的部分(比如,利用最左边前缀)时发生。对于之前的表的每一个行联合,
           全部记录都将从表中读出。这个类型严重依赖于根据索引匹配的记录多少—越少越好

range      这个连接类型使用索引返回一个范围中的行,比如使用>或<查找东西时发生的情况

index      这个连接类型对前面的表中的每一个记录联合进行完全扫描(比ALL更好,因为索引一般小于表数据)

ALL        这个连接类型对于前面的每一个记录联合进行完全扫描,这一般比较糟糕,应该尽量避免

Extra 字段值含义

Distinct         一旦MYSQL找到了与行相联合匹配的行,就不再搜索了

Not exists       MYSQL优化了LEFT JOIN,一旦它找到了匹配LEFT JOIN标准的行,就不再搜索了

Range checked for each Record (index map:#)  
                 没有找到理想的索引,因此对于从前面表中来的每一个行组合,MYSQL检查使用哪个索引,并用它来从表中返回行。
                 这是使用索引的最慢的连接之一

Using filesort   看到这个的时候,查询就需要优化了。MYSQL需要进行额外的步骤来发现如何对返回的行排序。
                 它根据连接类型以及存储排序键值和匹配条件的全部行的行指针来排序全部行

Using index      列数据是从仅仅使用了索引中的信息而没有读取实际的行动的表返回的,这发生在对表的全部的请求列都是同一个索引的部分的时候

Using temporary  看到这个的时候,查询需要优化了。这里,MYSQL需要创建一个临时表来存储结果,这通常发生在对不同的列集进行ORDER BY上,
                 而不是GROUP BY上

Using where      使用了WHERE从句来限制哪些行将与下一张表匹配或者是返回给用户。如果不想返回表中的全部行,并且连接类型ALL或index,
                 这就会发生,或者是查询有问题不同连接类型的解释(按照效率高低的顺序排序)

4. Mysql 引擎的选择

4.1 InnoDB

InnoDB是默认的事务型存储引擎,也是最重要,使用最广泛的存储引擎。在没有特殊情况下,一般优先使用InnoDB存储引擎。

1、数据存储形式
使用InnoDB时,会将数据表分为 .frm.idb 两个文件进行存储。

-rw-rw---- 1 mysql mysql       8705 May 28 16:45 WishList.frm
-rw-rw---- 1 mysql mysql     114688 Jul  2 10:55 WishList.ibd

.frm 存储表结构
.idb 存储表的数据和索引

2、锁的粒度
InnoDB采用MVCC(多版本并发控制)来支持高并发,InnoDB实现了四个隔离级别,默认级别是REPETABLE READ,并通过间隙锁策略防止幻读的出现。它的锁粒度是行锁。

MySQL大多数事务型存储引擎实现的都不是简单的行锁。基于提升并发性能的考虑,他们一般都同时实现了多版本并发控制(MVCC)。
可以认为MVCC是行级锁的一个变种,它能在大多数情况下避免加锁操作,因此开销更低。无论怎样实现,它们大豆实现了非阻塞的读操作,写操作也只锁定制定的行。
MVCC是通过保存数据在某一个时间点的快照来实现的,也就是说无论事务执行多久,每个事务看到的数据都是一致的。InnoDB的MVCC,是通过在每行记录后面保存两个隐藏的列来实现,这两个列一个保存了行的创建时间,一个保存了行的过期时间(或删除时间),当然,并非存储的是时间,而是系统版本号。每开启一个事务,版本号都会递增,事务开始时刻的系统版本号会作为事务的版本号。

3、事务
InnoDB是典型的事务型存储引擎,并且通过一些机制和工具,支持真正的热备份。

4、数据的存储特点
InnoDB表是基于聚簇索引索引建立的,聚簇索引索引对主键的查询有很高的性能,不过他的二级索引(非主键索引)必须包含主键列,索引其他的索引会很大。

索引分为聚簇索引非聚簇索引两种
聚簇索引也叫簇类索引,是一种对磁盘上实际数据重新组织以按指定的一个或多个列的值排序。由于聚簇索引的索引页面指针指向数据页面,所以使用聚簇索引查找数据几乎总是比使用非聚簇索引快。每张表只能建一个聚簇索引,并且建聚簇索引需要至少相当该表120%的附加空间,以存放该表的副本和索引中间页。
聚簇索引确定表中数据的物理顺序。聚簇索引类似于电话簿,后者按姓氏排列数据。由于聚簇索引规定数据在表中的物理存储顺序,因此一个表只能包含一个聚簇索引

4.2 MyISAM

1、数据存储形式
MyISAM采用的是索引与数据分离的形式,将数据保存在 .frm.MYD.MYI 三个文件中。

-rw-rw---- 1 mysql mysql      21716 Jul  2 09:24 Style.frm
-rw-rw---- 1 mysql mysql     260472 Jul  2 09:24 Style.MYD
-rw-rw---- 1 mysql mysql       5120 Jul  2 09:24 Style.MYI

.frm 存储表结构
.MYD 存储表的数据
.MYI 存储表的索引

2、锁的粒度
MyISAM不支持行锁,所以读取时对表加上共享锁,在写入是对表加上排他锁。由于是对整张表加锁,相比InnoDB,在并发写入时效率很低。

3、事务
MyISAM不支持事务。

4、数据的存储特点
MyISAM是基于非聚簇索引进行存储的。

5、其他
MyISAM提供了大量的特性,包括全文索引,压缩,空间函数,延迟更新索引键等。
进行压缩后的表是不能进行修改的,但是压缩表可以极大减少磁盘占用空间,因此也可以减少磁盘IO,从而提供查询性能。
延迟更新索引键,不会将更新的索引数据立即写入到磁盘,而是会写到内存中的缓冲区中,只有在清除缓冲区时候才会将对应的索引写入磁盘,这种方式大大提升了写入性能。

4.3 两者对比

两种存储引擎各有各的有点,MyISAM专注性能,InnoDB专注事务。两者最大的区别就是InnoDB支持事务,和行锁。


33.jpg

若数据库的数量在百万级以上,且数据修改较少,使用InnoDB引擎可能会比较慢, MyISAM是个更好的选择。

为什么 MyISAM 会比 Innodb 的查询速度快
InnoDB 在做SELECT的时候,要维护的东西比MYISAM引擎多很多;
1)InnoDB 要缓存数据和索引,MyISAM只缓存索引块,这中间还有换进换出的减少
2)InnoDB 寻址要映射到块,再到行,MyISAM记录的直接是文件的OFFSET,定位比INNODB要快
3)InnoDB 还需要维护MVCC一致;虽然你的场景没有,但他还是需要去检查和维护MVCC ( Multi-Version Concurrency Control )多版本并发控制

InnoDB :通过为每一行记录添加两个额外的隐藏的值来实现MVCC,这两个值一个记录这行数据何时被创建,另外一个记录这行数据何时过期(或者被删除)。但是InnoDB并不存储这些事件发生时的实际时间,相反它只存储这些事件发生时的系统版本号。这是一个随着事务的创建而不断增长的数字。每个事务在事务开始时会记录它自己的系统版本号。每个查询必须去检查每行数据的版本号与事务的版本号是否相同。让我们来看看当隔离级别是REPEATABLE READ时这种策略是如何应用到特定的操作的

SELECT InnoDB必须每行数据来保证它符合两个条件
1、InnoDB必须找到一个行的版本,它至少要和事务的版本一样老(也即它的版本号不大于事务的版本号)。这保证了不管是事务开始之前,或者事务创建时,或者修改了这行数据的时候,这行数据是存在的。
2、这行数据的删除版本必须是未定义的或者比事务版本要大。这可以保证在事务开始之前这行数据没有被删除。

为什么 MyISAM 会比 Innodb 的插入数据速度快
MyISAM使用了三个文件来存储数据,frm后缀存储表结构、MYD存储真实数据、MYI存储索引数据。
每次进行插入时,MYD的内容是递增插入,MYI是一个B+树结构,每次的索引变更需要重新组织数据。

5. Mysql 引擎切换

查看当前数据库的所支持的数据库引擎以及默认数据库引擎

show engines;
44.png

切换方式1:
修改 mysql 配置文件my.cnf

在[mysqld]最后添加为上

default-storage-engine=InnoDB

重启mysql服务, mysql相关操作见《LNMP安装手册》

service mysqld restart

数据库默认的引擎修改为InnoDB,这种方式整个数据库的引擎都会改变,如果只希望改某几张表的引擎使用第二种方式

切换方式2:
在建表的时候指定或者建完表修改

建表的时候指定

create table 表名(   
    id int primary key,   
    name varchar(50)   
)type=MyISAM;

建完表后修改

alter table mytbl2 type = InnoDB;

也可以直接在 Navicat Premium 工具中在表上右键-》设计表-》选项 里面修改


22.png
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,847评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,208评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,587评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,942评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,332评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,587评论 1 218
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,853评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,568评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,273评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,542评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,033评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,373评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,031评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,073评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,830评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,628评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,537评论 2 269

推荐阅读更多精彩内容