1.explain分析
explian引用
索引基数
show indexes from table_name;
主键索引具有最好的基数
测试时
不走缓存
SELECT SQL_NO_CACHE id from test_null;
2.更好的索引类型
索引列尽可能的为not null ,避免在可空的列索引上进行二次扫描
要尽量避免 NULL ,关于索引列为Null的是否走索引,见测试 索引列的值为null查询时走索引的情况
3.使用unique index
与常规索引比不需要进行索引范围扫描
4.使用primary key
主键是uniquekey的一种特殊形式 。在innodb中,一个uniquekey是一个聚集索引(即对磁盘上数据排列的索引),当数据按照主键的次序进行检索时会极大改进性能
5.索引太多是有害的
例如,如果possible_keys 列表中有超过3个的索引,mysql优化器有太多信息而无法确定最好使用哪个索引,也就意味着有些是低效或者无用的索引
6.索引列使用最小可能的数据类型
比如在一个varchar(100)甚至更大的列上建立索引,一种改进方法是建立一个额外的列,并在包含较大的varchar(100)列的md5值的额外varchar(32)列上创建索引。
更好的方法是使用bigint来存储md5值的数字表示,数字索引更加高效
CONV(N,from_base,to_base)
mysql> select conv('a',16,10); +-----------------+ | conv('a',16,10) | +-----------------+ | 10 | +-----------------+ mysql> select conv(substr(md5('abc'),1,16),16,10); +-------------------------------------+ | conv(substr(md5('abc'),1,16),16,10) | +-------------------------------------+ | 10376663631224000432 | +-------------------------------------+
7.建立索引时
如果使用到多个列,定义多列索引
哪列的唯一性更高(基数大 show indexes from table_name),哪列优先放在多列索引的前面
覆盖索引是理性的索引 (explain 里extra的信息时using index)
覆盖索引包括所有需要的列,但是不需要读取单独的数据页,实际意味着不需要读取数据存储,只利用索引数据就可以检索到实际想要的查询的数据
在myisam表里,意味着只要读入索引就可以得到问题的记录,在innodb中 索引和数据是位于同一个文件中的,但仍然会高效些,因为只需要读入索引
优化部分索引的性能
select type from tb where sid=1
建立(sid,type)的索引 就是覆盖索引,比单独在sid,type上建索引要快
与其在长字符的列上定义索引,还不如只在左边的一小部分上建立索引
8.一些常见的不使用索引的情况
开始字符是通配符是,或者 在索引列上使用标量函数
like "%123",upper()
字符串类型的查询不加引号
9.覆盖索引的左前缀原则
10.更详细的分析
set profiling=1;
select * from table;
show profile;
show profile source ;
mysql> select * from test_null where mark like 'aaa9999%'; +------+---------+ | id | mark | +------+---------+ | 9999 | aaa9999 | +------+---------+ 1 row in set mysql> show profile; +----------------------+----------+ | Status | Duration | +----------------------+----------+ | starting | 5.5E-5 | | checking permissions | 1.1E-5 | | Opening tables | 2E-5 | | init | 2.4E-5 | | System lock | 7E-6 | | optimizing | 8E-6 | | statistics | 1.4E-5 | | preparing | 7E-6 | | executing | 2E-6 | | Sending data | 0.006271 | | end | 5.7E-5 | | query end | 3.6E-5 | | closing tables | 5.1E-5 | | freeing items | 0.000348 | | cleaning up | 0.00011 | +----------------------+----------+ mysql> show profile source; +----------------------+----------+-----------------------+----------------------+-------------+ | Status | Duration | Source_function | Source_file | Source_line | +----------------------+----------+-----------------------+----------------------+-------------+ | starting | 5.5E-5 | NULL | NULL | NULL | | checking permissions | 1.1E-5 | check_access | sql_authorization.cc | 835 | | Opening tables | 2E-5 | open_tables | sql_base.cc | 5648 | | init | 2.4E-5 | handle_query | sql_select.cc | 121 | | System lock | 7E-6 | mysql_lock_tables | lock.cc | 321 | | optimizing | 8E-6 | JOIN::optimize | sql_optimizer.cc | 151 | | statistics | 1.4E-5 | JOIN::optimize | sql_optimizer.cc | 367 | | preparing | 7E-6 | JOIN::optimize | sql_optimizer.cc | 475 | | executing | 2E-6 | JOIN::exec | sql_executor.cc | 119 | | Sending data | 0.006271 | JOIN::exec | sql_executor.cc | 195 | | end | 5.7E-5 | handle_query | sql_select.cc | 199 | | query end | 3.6E-5 | mysql_execute_command | sql_parse.cc | 4952 | | closing tables | 5.1E-5 | mysql_execute_command | sql_parse.cc | 5004 | | freeing items | 0.000348 | mysql_parse | sql_parse.cc | 5578 | | cleaning up | 0.00011 | dispatch_command | sql_parse.cc | 1864 | +----------------------+----------+-----------------------+----------------------+-------------+
mysql> set profiling=1; Query OK, 0 rows affected mysql> select * from a; +----+-----+-------+ | id | uid | phone | +----+-----+-------+ | 1 | 1 | 22 | | 2 | 2 | 33 | | 3 | 3 | 33 | | 4 | 4 | 22 | | 5 | 5 | 22 | +----+-----+-------+ 5 rows in set mysql> select * from b; +-------+ | phone | +-------+ | 1111 | | 2222 | | 3333 | | 4444 | +-------+ 4 rows in set mysql> show profiles; +----------+------------+-----------------+ | Query_ID | Duration | Query | +----------+------------+-----------------+ | 1 | 0.00025225 | select * from a | | 2 | 0.0009805 | select * from b | +----------+------------+-----------------+ 2 rows in set mysql> show profile for query 2; +----------------------+----------+ | Status | Duration | +----------------------+----------+ | starting | 0.000106 | | checking permissions | 1.4E-5 | | Opening tables | 3.3E-5 | | init | 3E-5 | | System lock | 2E-5 | | optimizing | 0.000259 | | statistics | 4.5E-5 | | preparing | 2.5E-5 | | executing | 4E-6 | | Sending data | 0.000358 | | end | 7E-6 | | query end | 6E-6 | | closing tables | 8E-6 | | freeing items | 5.4E-5 | | cleaning up | 1.4E-5 | +----------------------+----------+ 15 rows in set