Mysql性能优化——实战篇
1、什么是单列索引、组合索引?
单列索引:就是对某一个列建立索引,比如只对username这列建立索引(对where后面的列创建索引)
add index(username(10))。
查询语句:
select column from tbl_user where username=?;
组合索引:顾名思义多一个列建立索引,比如对username, email, address建立索引
add index(username(10), email(12), address(10))。
查询语句:
select column from tbl_user where username=? and email=? and address=?
2、如何设置索引
对于varchar等类型他的长度是不固定的,为了提高检索效率,我们一般会对字段取前面的固定几位进行索引,比如上面的username取10位。
3、什么是左侧原则
add index(username(10), email(12), address(10))。
查询语句:
select column from tbl_user where email=? and address=?
考虑上面这个语句有什么问题?效率为什么低?
原因:建立上面这样的组合索引,其实数据库中相当于分别建立了以下三条:
add index(username(10)
add index(useranem(10), email(12))
add index(username(10), email(12), address(10))
上面就是所谓的“左侧原则”,从最左边的开始进行组合。
所以:下面几个效率会低,因为他找不到索引
select column from tbl_user where email=? and address=?
select column from tbl_user where email=?
select column from tbl_user where address=?
下面几个效率会高,因为他找到索引
select column from tbl_user where username=? and email=? and address=?
select column from tbl_user where username=? and email=?
select column from tbl_user where username=?
4、遇到or,如何写sql语句?
add index(username(10), email(12), address(10))。
查询语句:
select column from tbl_user where username=? or email=?
上面的查询语句很鸡肋,没办法靠索引方式来,怎么办了?优化sql语句(自我组合)。
则需要建立email索引,并用以下sql语句union
add index(email(12))
查询语句:
select column from tbl_user where username=? union select column from tbl_user where email=?
对于text必须使用MyISAM存储引擎
CREATE TABLE articles (
id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,
title VARCHAR(200),
body TEXT,
FULLTEXT (body)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
查询的时候:
SELECT * FROM articles
WHERE MATCH (body) AGAINST ('database');
比如:tbl_article
article_id |
title |
content |
add_time |
author |
hit |
int |
varchar |
text |
timestamp |
varchar |
int |
将大数据字段进行水平剥离content字段:
现优化如下:
比如:tbl_ article(使用innodb,hit字段经常更新)
article _id |
Cotent |
content_id |
add_time |
author |
hit |
int |
varchar |
int |
timestamp |
varchar |
int |
tbl_content:(使用MyISAM,支持全文检索)
content _id |
cotent |
int |
varchar |
这样就可以把tbl_article数据列转换成固定的数据行格式,减少表的碎片,在查询的时候运行select * 不会通过网络传输大量的content内容了。性能上大大的提高了。
使用unsigned int来表示ip地址,比如:10.204.79.125,他存储的时候是:
“10*2^24+204*2^16+79*2^8+125”计算的值
注意:java中需要使用long来进行操作。
user_id |
ip |
int |
unsigned int |
建议使用unsigned int来保存,如果使用DateTime类型来保存,见下面例子
select * from tbl_user where date(add_time) between ‘2012-12-1’ and ‘2012-12-10’
需要转化获取日期,date函数结果对索引无效。所以上面的方式在检索的时候效率很慢(无法使用索引)
请使用如下方式保存字段:
user_id |
add_time |
int |
unsigned int |
查询的时候(时间是秒数)
select * from tbl_user where add_time>123123125553 and addtime<1231231235