mysql> select distinct(password) from one;
+----------+
| password |
+----------+
| 234567 |
| 345678 |
| 456789 |
| 123456 |
+----------+
4 rows in set (0.08 sec)
可以看出password列中只有这几个值,当然在现实中不可能密码有这么多一样的,再说数据也可能不断更新,这里只是举例说明补 洞的方法
mysql> explain select * from one where username='abgvwfnt' and password in('123456','234567','345678','456789') and last_login='1338251170';
+----+-------------+-------+-------+---------------+----------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+-------+---------------+----------+---------+------+------+-------------+
| 1 | SIMPLE | one | range | username | username| 83 | NULL |4 | Using where |
+----+-------------+-------+-------+---------------+----------+---------+------+------+-------------+
1 row in set (0.00 sec)
可以看出ref=83 所有的索引都用到了,type=range是因为用了in子句。 这个被“补洞”列中的值应该是有限的,可预知的,如性别,其值只有男和女(加多一个不男不女也无妨)。 “补洞”方法也有瓶颈,当很多列,且需要补洞的相应列(可以多列)的值虽有限但很多(如中国城市)的时候,优化器在优化时组合 起来的数量是很大,这样的话就要做好基准测试和性能分析,权衡得失,取得一个合理的优化方法。
like
mysql> explain select * from one where username like 'abgvwfnt%';
+----+-------------+-------+-------+---------------+----------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref |
rows | Extra |
+----+-------------+-------+-------+---------------+----------+---------+------+------+-------------+
| 1 | SIMPLE | one | range | username | username | 24 | NULL | 5 | Using where |
+----+-------------+-------+-------+---------------+----------+---------+------+------+-------------+
1 row in set (0.00 sec)
mysql> explain select * from one where username like '%abgvwfnt%';
+----+-------------+-------+------+---------------+------+---------+------+-------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows| Extra |
+----+-------------+-------+------+---------------+------+---------+------+-------+-------------+
| 1 | SIMPLE | one | ALL | NULL | NULL | NULL | NULL | 20259 | Using where |
+----+-------------+-------+------+---------------+------+---------+------+-------+-------------+
1 row in set (0.01 sec)
对比就知道like操作abgvwfnt%能用到索引,%abgvwfnt%用不到
Order by 优化
filesort优化算法
在mysql version()<4.1之前,优化器采用的是filesort第一种优化算法,先提取键值和指针,排序后再去提取数据,前后要搜索数据 两次,第一次若能使用索引则使用,第二次是随机读(当然不同引擎也不同)。mysql version()>=4.1,更新了一个新算法,就是在第 一次读的时候也把selcet的列也读出来,然后在sort_buffer_size中排序(不够大则建临时表保存排序顺序),这算法只需要一次读 取数据。所以有这个广为人传的一个优化方法,那就是增大sort_buffer_size。Filesort第二种算法要用到更多空间, sort_buffer_size不够大反而会影响速度,所以mysql开发团队定了个变量max_length_for_sort_data,当算法中读出来的需要列 的数据的大小超过该变量的值才使用,所以一般性能分析的时候会尝试把max_length_for_sort_data改小。
单独order by 用不了索引,索引考虑加where 或加limit
先建一个索引(last_login),建的过程就不给出了
mysql> explain select * from one order by last_login desc;
+----+-------------+-------+------+---------------+------+---------+------+-------+----------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows
| Extra |
+----+-------------+-------+------+---------------+------+---------+------+-------+----------------+
| 1 | SIMPLE | one | ALL | NULL | NULL | NULL | NULL | 2046
3 | Using filesort |
+----+-------------+-------+------+---------------+------+---------+------+-------+----------------+
1 row in set (0.00 sec)
mysql> explain select * from one order by last_login desc limit 10;
+----+-------------+--