mysql查询优化

查询优化
在优化MySQL时,通常需要对数据库进行分析。常见的分析手段有慢查询日志,EXPLAIN分析查询,通过定位分析性能的瓶颈,才能更好的优化数据库系统的性能。

慢查询

1.1 慢查询日志开启
在配置文件my.cnf(linux)或者my.ini(windows)中在[mysqld]一行下面加入两个配置参数
log-slow-queries=/data/mysqldata/slow-query.log
long_query_time=5

注:log-slow-queries参数为慢查询日志存放的位置,一般这个目录要有mysql的运行账号的可写权限,一般都将这个目录设置为mysql的数据存放目录;
long_query_time=5 中的5表示查询超过5秒才记录

还可以在my.cnf或者my.ini中添加log-queries-not-using-indexes参数,表示记录下没有使用索引的查询。

1.2 慢查询分析
我们可以通过打开log文件查看得知哪些sql执行效率低下
从日志中,可以发现查询时间超过5秒的sql,而小于5秒的没有出现在些日志中。

如果慢查询日志中记录内容很多,可以使用mysqldumpslow工具(MySQL客户端安装自带)来对慢查询日志进行分类汇总。mysqldumpslow对日志文件进行了分类汇总,显示汇总后摘要结果。

进入log的存放目录,运行
[root]# mysqldumpslow slow-query.log

mysqldumpslow命令

/path/mysqldumpslow -s c -t 10 /database/mysql/slow-query.log
这会输出记录次数最多的10条sql语句,其中:

-s,表示是按何种方式排序,c t l r分别是按照记录次数、时间、查询时间、返回的记录数来排序,
ac at al ar,表示相应的倒序
-t,是top n的意思,即为返回前面多少条的数据;
-g,后面可以写一个正则匹配模式,大小写不敏感

例如:
/path/mysqldumpslow -s r -t 10 /database/mysql/slow-query.log
得到返回记录集最多的10个查询
/path/mysqldumpslow -s t -t 10 -g “left join" /database/mysql/slow-query.log
得到按照时间排序的前10条里面含有左连接的查询语句

使用mysqldumpslow命令可以非常明确的得到各种我们需要的查询语句,对Mysql查询语句的监控、分析、优化是mysql优化非常重要的一步。开启慢查询日志后,由于日志记录操作,在一定程序上会占用CPU资源影响mysql的性能,但是可以阶段性开启来定位性能瓶颈。

2 EXPLAIN
在mysql中可以使用explain查看sql执行计划,用法 explain select * from products;

2.1 id
select识别符。这是select查询序列号。这个不重要。

2.2 select_type
表示select语句的类型

例如:
1)、simple
表示简单查询,其中不包含连接查询和子查询。
2)、primary
表示主查询,或者是最外面的查询语句。
3)、union
表示连接查询的第2个或者后面的查询语句

2.3 table
表示查询的表。

2.4 type
表示表的连接类型。
以下的连接类型的顺序是从最佳类型到最差类型:

1)、system
表仅有一行,这是const类型的特列,平时不会出现,这个也可以忽略不计。

2)、const
数据表最多只有一个匹配行,因为只匹配一行数据,所以很快

3)、eg_ref
mysql手册是这样说的:”对于每个来自于前面的表的行组合,从该表中读取一行。这可能是最好的联接类型,除了const类型。它用在一个索引的所有部分被联连使用并且索引是unique或primary key"。eq_ref可以用于使用=比较带索引的列。

4)、ref
查询条件索引即不是unique,也不是primary key的情况。ref可用于=或者<或>操作符的带索引的列。

5)、ref_or_null
该联接类型如同ref,但是添加了mysql可以专门搜索包含NULL值的行。在解决子查询中经常使用该联接类型的优化。

上面这五种情况都是很理想的索引使用情况。

6)、index_merge
该联接类型表示使用了索引合并优化方法。在这种情况下,key列包含了使用的索引的清单,key_len包含了使用的索引的最长的关键元素。

7)、unique_subquery
该类型替换了下面形式的IN子查询的ref: value IN(SELECT primary_key FROM single_table WHERE some_expr)
unique_subquery是一个索引查找函数,可以完全替换子查询,效率更高。

8)、index_subquery
该联接类型类似于unique_subquery。可以替换IN子查询,但只适合下列形式的子查询中的非唯一索引:value IN(SELECT key_column FROM single_table WHERE some_expr)

9)、 range
只检索给定范围的行,使用一个索引来选择行。

10)、index
该联接类型与ALL相同,除了只有索引树被扫描。这通常比ALL快,因为索引文件通常比数据文件小。

11)、all
对于每个来自于先前的表的行组合,进行完整的表扫描。(性能最差)

2.5 possible_keys

批出mysql能使用哪个索引在该表中找到行。
如果该列为NULL,说明没有使用索引,可以对该列创建索引来提高性能。

2.6 key

显示mysql实际决定使用的键(索引)。如果没有选择索引,键是NULL。

2.7 key_len

显示mysql决定使用的键长度。如果键是NULL,则长度为NULL

注意:key_len是确定了mysql将实际使用的索引长度。

2.8 ref
显示使用哪个列或者常数为key一起从表中选择行。

2.9 rows
显示mysql认为它执行查询时必须检查的行数。

2.10 extra
该列包含mysql解决查询的详细信息。

3.1 创建索引

是否创建索引,几点原则:
较频繁的作为查询条件的字段应该创建索引;
唯一性太差的字段不适合单独创建索引,即使频繁作为查询条件;
更新非常频繁的字段不适合创建索引;
不会出现在where子名中的字段不该创建索引;

索引能够极大的提高数据检索效率,也能够改善排序分组操作的性能,但是我们不能忽略的一个问题就是索引是完全独立于基础数据之外的一部分数据,更新数据会带来IO量和调整索引所致的计算量的资源消耗。

3.2 使用索引

3.2.1 使用联合索引的查询
mysql可以为多个字段创建索引,一个索引可以包括16个字段。对于联合索引,只有查询条件中使用了这些字段中的第一个字段时,索引才生效。

3.2.2 使用 OR 关键字的查询
查询语句的查询条件中只有OR关键字,且OR前后的两个条件中列都是索引时,索引才会生效,否则,索引不生效。

MyISAM和InnoDB区别:前者不支持事务,查询快

MyISAM存储优化:

4.1 禁用索引
大量插入前禁用,插入完成后再开启

禁用索引的语句:
alter table table_name disable keys

开启索引语句:
alter table table_name keys

对于空表不需要,MyISAM引擎是在导入数据后才建立索引

4.2 禁用唯一性检查

同上
禁用唯一性检查的语句:
set unique_checks=0;

开启唯一性检查的语句:
set unique_checks=1;

4.3 批量插入数据
插入数据时,可以使用一条INSERT语句插入一条数据,也可以插入多条数据。

一条插入多个速度比较快。

4.4 使用load data infile

当需要批量导入数据时,使用load data infile 语句比insert语句快很多。

InnoDb

5.1 禁用唯一性检查
同上
5.2 禁用外键检查
插入数据之前执行禁止对外键的检查,数据插入完成后再恢复,可以提升插入速度。

禁用: set foreign_key_checks=0;
开启: set foreign_key_checks=1;

5.3 禁止自动提交
插入数据之前执行禁止事务的自动提交,数据插入完成后再恢复,可以提高插入速度。

禁用: set autocommit=0;
开启: set autocommit=1;

一般开发时不用,生产时使用。

数据库结构优化
6.1 优化表结构

  • 尽量将表字段定义为not null约束,这时由于在mysql中含有空值的列很难进行查询优化,null值会使索引以及索引的统计信息变得很复杂。
  • 对于只包含特定类型的字段,可以使用enum、set等符合数据类型。
  • 数值型字段的比较比字符串的比较效率高得多,字段类型尽量使用最小、最简单的数据类型。例如P地址可以使用int类型。
  • 尽量使用tinyint、smallint、medium_int作为整数类型而非int,如果非负则加上unsigned
  • varchar的长度只分配真正需要的空间
  • 尽量使用timestamp而非datetime
  • 单表不要有太多字段,建议在20以内
  • 合理的加入冗余字段可以提高查询速度。

6.2 表拆分
6.2.1 垂直拆分
方法: 如果表字段太多,比常用的拆分到一张表,不常用的拆分到另一张表。
取的时候,分表取两次,比用join效率高
6.2.2 水平拆分
例子:对id求余,对余数进行分析,然后拆表 如果id % 3 = 0~2 折成了3张表。

水平拆分按照行进行拆分,常见的就是分库分表。以用户表为例,可以取用户ID,然后对ID取10的余数,将用户均匀的分配进这0-9这个10个表中。查找的时候也按照这种规则,又快又方便。

有些表业务关联比较强,那么可以使用按时间划分的。例如每天的数据量很大,需要每天新建一张表。这种业务类型就是需要调整插入,但是对于查询的效率不太关心。表越大,插入数据所需要索引维护的时间也就越长。

两种方式:
1、动态数据源
2、myCat数据中间件,可以用在此处。
6.3 分区
mysql主要支持4种模式的分区:range分区、list预定义列表分区,hash分区,key键值分区。

不复杂,配置就可以

6.4 读写分离

我们发现一般情况下对数据库而言都是“读多写少”,也就是对数据库读取数据的压力比较大,这样分析可以采用数据库集群的方案。其中一个是主库,负责写入数据,我们称为写库;其他都是从库,负责读取数据,我们称为读库。这样可以缓解一台服务器的访问压力。

6.5 数据库集群

如果访问量非常大,虽然使用读写分离能够缓解压力,但是一旦写操作一台服务器都不能承受了,这个时候我们就需要考虑使用多台服务器实现读写操作。

例如可以使用MyCat搭建Mysql集群,对ID求3的余数,这样可以把数据分别存到3台不同的服务器上,由MyCat负责维护集群节点的使用。

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

推荐阅读更多精彩内容