您的位置:首页 > 数据库 > MySQL

MySQL索引及优化

2015-11-18 20:21 375 查看

MySQL索引及优化

索引分类

唯一索引

强调唯一,就是索引值必须唯一,关键字unique index

创建索引:

1、create unique index 索引名 on 表名(列名);

2、alter table 表名 add unique index 索引名 (列名);

删除索引:

1、 drop index 索引名 on 表名;

2、 alter table 表名 drop index 索引名;

主键是唯一索引的一种

全文索引

InnoDB不支持,Myisam支持性能比较好,一般在 CHAR、VARCHAR 或 TEXT 列上创建。

Create table 表名(

id int not null primary anto_increment,

title varchar(100),

FULLTEXT(title)

)type=myisam

单列索引与多列索引

索引可以是单列索引也可以是多列索引(也叫复合索引)。

create table test3 (

id int not null primary key auto_increment,

uname char(8) not null default ”,

password char(12) not null,

INDEX(uname,password)

)type=myisam;

聚集索引(聚簇索引)

一种索引,该索引中键值的逻辑顺序决定了表中相应行的物理顺序。聚集索引确定表中数据的物理顺序。Mysql中myisam表是没有聚集索引的,innodb有(主键就是聚集索引)

MYISAM和INNODB索引结构

B-tree和B+-tree

索引优化技巧

表数据类型选择

能小用小

避免用NULL,所有列值尽量NOT NULL

char和varchar选择

属性CharVarchar
值域大小最长字符数是255,超过截断65535个字节,动态变化
储存空间固定空间节约空间,但更新可能发生变化
适用场合适用于存储很短或固定或长度相似字符当最大长度远大于平均长度并且发生更新的时候
整型、整形优先原则

Tinyint、smallint、mediumint、int、bigint,分别需要8、16、24、32、64

值域范围:-2^(n-1)~ 2^(n-1)-1

笔者建议:能用tinyint的绝不用smallint

误区:int(1) 和int(11)是一样的,唯一区别是mysql客户端显示的时候显示多少位。

整形优先原则:能用整形的不用其他类型替换,如ip可以转换成整形保存,如商品价格‘50.00元’则保存成50

精确度与空间的转换

在存储相同数值范围的数据时,浮点数类型通常都会比DECIMAL类型使用更少的空间。FLOAT字段使用4字节存储,DOUBLE类型需要8 个字节并拥有更高的精确度和更大的数值范围,DECIMAL类型的数据将会转换成DOUBLE类型。

sql语句优化

索引的最左前缀原则

定义:最左前缀原则指的的是在sql where 字句中一些条件或表达式中出现的列的顺序要保持和多索引的一致或以多列索引顺序出现,只要出现非顺序出现、断层都无法利用到多列索引。

举例说明:一个多列索引(username,password,last_login),当三列在where中出现的顺序如(username,password,last_login)、(username,password)、(username)才能用到索引,如下面几个顺序(password,last_login)、(passwrod)、(last_login)—这三者不从username开始,(username,last_login)—断层,少了password,都无法利用到索引,如果是(username,last_login)则只能用到username的索引

Ps:最左前缀原则中where字句有or出现还是会遍历全表

Ps2: Where 子句表达式虽然顺序是(username,password, last_login)或(username,password)但第一个是有范围’<’、’>’,’<=’,’>=’等出现,不用索引

Ps3: 能利用索引到首先出现范围的一列

比如: where username=’abgvwfnt’ and password >’123456′and last_login=’1338251170,虽然按照顺序使用,但是password出现>则只能用到username索引

Ps4:like操作前缀匹配可以用索引,如username like ‘abde%’,而username like ‘%bbbb’和username like ‘%abde%’不能使用username索引

Order by优化

单独order by 用不了索引,索引考虑加where 或加limit

select * from one order by last_login desc; 会using filesort

select * from one order by last_login desc limit 10; 可以用索引

where + orerby 类型: where满足最左前缀原则,且orderby的列是where子句用到的索引的列的子集(order by的列不需要满足最左前缀原则),则不用filesort,下面两句中,句1不用filesort,句2会有filesort

句1: select * from one where username=’abgvwfnt’ and password =’123456’ and last_login=’1338251001’ order by password desc,last_login desc;

句2: select * from one where username=’abgvwfnt’ and password =’123456’ and last_login=’1338251001’ order by password desc,level desc;

where + orerby+limit类型: 与 where + orerby 类型一致,limit不产生影响

尽量在比较常用的oder by的列和where中常用的列建立多列索引

隔离列: 是指查询语句中把索引列隔离出来,也就是说不能在语句中把列包含进表达式中,如id+1=2、inet_aton(’210.38.196.138′)—ip转换成整数、convert(123,char(3))—数字转换成字符串、date函数等mysql内置的大多函数都是非隔离列。

下面两句中,句1可以用索引,句2不可以

select * from one where last_login = 8388605;

select * from one where last_login +1= 8388606 ;

OR、IN、UNION ALL,可以尝试用UNION ALL

or会遍历表

in的使用: in里面如果是常量的话,可一大胆的用in

UNION All 直接返回并集,可以避免去重的开销

不要使用嵌套子查询

避免多余索引

比如: (username), (username, password), (username, password, last_login)三个索引中(username)是多余的,因为后面两个都可以满足第一个的需求,(username, password)也是多余的,因为第三个可以满足

系统配置与优化

重要变量

key_buffer_size: 索引块缓存区大小, 针对MyISAM存储引擎,该值越大,性能越好.但是超过操作系统能承受的最大值,反而会使mysql变得不稳定. —-这是很重要的参数

sort_buffer_size: 这是索引在排序缓冲区大小,若排序数据大小超过该值,则创建临时文件,注意和myisam_sort_buffer_size的区别—-这是很重要的参数

read_rnd_buffer_size: 当排序后按排序后的顺序读取行时,则通过该缓冲区读取行,避免搜索硬盘。将该变量设置为较大的值可以大大改进ORDER BY的性能。但是,这是为每个客户端分配的缓冲区,因此你不应将全局变量设置为较大的值。相反,只为需要运行大查询的客户端更改会话变量

join_buffer_size: 用于表间关联(join)的缓存大小

tmp_table_size缓存表的大小

table_cache: 允许 MySQL 打开的表的最大个数,并且这些都cache在内存中

delay_key_write: 针对MyISAM存储引擎,延迟更新索引.意思是说,update记录时,先将数据up到磁盘,但不up索引,将索引存在内存里,当表关闭时,将内存索引,写到磁盘

更多参数查看http://www
4000
.phpben.com/?post=70

optimize、Analyze、check、repair维护操作

optimize: 数据在插入,更新,删除的时候难免一些数据迁移,分页,之后就出现一些碎片,久而久之碎片积累起来影响性能,这就需要DBA定期的优化数据库减少碎片,这就通过optimize命令

如对MyisAM表操作:
optimize table 表名


对于InnoDB表是不支持optimize操作,否则提示“Table does not support optimize, doing recreate + analyze instead”,当然也可以通过命令:
alter table one type=innodb;
来替代。

Analyze: 用来分析和存储表的关键字的分布,使得系统获得准确的统计信息,影响 SQL 的执行计划的生成。对于数据基本没有发生变化的表,是不需要经常进行表分析的。但是如果表的数据量变化很明显,用户感觉实际的执行计划和预期的执行计划不 同的时候,执行一次表分析可能有助于产生预期的执行计划。

Analyze table 表名


Check: 检查表或者视图是否存在错误,对 MyISAM 和 InnoDB 存储引擎的表有作用。对于 MyISAM 存储引擎的表进行表检查,也会同时更新关键字统计数据

Repair: optimize需要有足够的硬盘空间,否则可能会破坏表,导致不能操作,那就要用上repair,注意INNODB不支持repair操作

图说mysql查询执行流程



查询缓存,判断sql语句是否完全匹配,再判断是否有权限,两个判断为假则到解析器解析语句,为真则提取数据结果返回给用户。

解析器解析。解析器先词法分析,语法分析,检查错误比如引号有没闭合等,然后生成解析树。

预处理。预处理解决解析器无法决解的语义,如检查表和列是否存在,别名是否有错,生成新的解析树。

优化器做大量的优化操作。

(1) 生成执行计划。

(2) 查询执行引擎,负责调度引擎获取相应数据

(3) 返回结果。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  mysql 优化 索引