提供了相似于书中目录的做用,目的是为了优化查询html
大的分类:mysql
B树索引 Hash索引 R树 Full text GIS #地图类索引 ------------------------------- #B树基于不一样的查找算法分类: B-tree 如下两种类型在范围查询方面提供了更好的性能(> < >= <=) B+Tree B*Tree
1)辅助索引(S)怎么构建B树结构的?linux
2)辅助索引细分面试
1)前提redis
2)汇集索引(C)怎么构建B树结构的?算法
1)数据量级, 解决方法:分表,分库,分布式sql
2)索引列值过长 , 解决方法:前缀索引mongodb
3)数据类型: 数据库
变长长度字符串,使用了char,解决方案:变长字符串使用varcharvim
enum类型的使用enum ('山东','河北','黑龙江','吉林','辽宁','陕西'......)
mysql> desc city; +-------------+----------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-------------+----------+------+-----+---------+----------------+ | ID | int(11) | NO | PRI | NULL | auto_increment | | Name | char(35) | NO | | | | | CountryCode | char(3) | NO | MUL | | | | District | char(20) | NO | | | | | Population | int(11) | NO | | 0 | | +-------------+----------+------+-----+---------+----------------+ Field :列名字 key :有没有索引,索引类型 PRI: 主键索引 UNI: 惟一索引 MUL: 辅助索引(单列,联和,前缀) mysql> show index from city; +-------+------------+-------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+ | Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | +-------+------------+-------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+ | city | 0 | PRIMARY | 1 | ID | A | 4188 | NULL | NULL | | BTREE | | | | city | 1 | CountryCode | 1 | CountryCode | A | 4188 | NULL | NULL | | BTREE | | | +-------+------------+-------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
1)建立索引
alter table city add index idx_name(name); #方法一 create index idx_name1 on city(name); #方法二 show index from city;
2)删除索引
alter table city drop index idx_name1; #直接删除索引名称便可
3)覆盖索引(联合索引)
alter table city add key idx_co_po(countrycode,population); #多个字段上创建索引 alter table city add index idx_co_po(countrycode,population); #多个字段上创建索引
4)前缀索引
alter table city add index idx_di(district(5)); #在前5个字符上创建索引
5)惟一索引
alter table city add unique index idx_uni1(name); ERROR 1062 (23000): Duplicate entry 'San Jose' for key 'idx_uni1' #惟一键冲突
获取到的是优化器选择完成的,他认为代价最小的执行计划.
做用: 语句执行前,先看执行计划信息,能够有效的防止性能较差的语句带来的性能问题.
1. 全表扫描(应当尽可能避免,由于性能低)
2. 索引扫描
3. 获取不到数据
获取优化器选择后的执行计划:explain或者desc
explain select SQL_NO_CACHE * from test where name='AAA'\G #SQL_NO_CACHE的做用是禁止缓存查询结果。
mysql> desc select * from city where countrycode='CHN'\G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: city partitions: NULL type: ref possible_keys: CountryCode key: CountryCode key_len: 3 ref: const rows: 363 filtered: 100.00 Extra: NULL --------------------------------------------------------------- #执行计划相关信息分析: table: city #查询操做的表 possible_keys: CountryCode,idx_co_po #可能会走的索引 key: CountryCode #真正走的索引 type: ref #索引类型 Extra: Using index condition #额外信息
以下为索引类型,从左到右性能依次变好.
ALL #全表扫描 index #全索引扫描 range #索引范围查询 ref #辅助索引的等值查询 eq_ref #多表链接的表,On的条件是主键或惟一键 system(const) #主键或惟一键的等值查询 NULL #索引中扫描不到这个数据
在索引扫描类型方面,至少保证在range以上级别。
desc select * from city; desc select * from city where name like '%C%'; desc select * from city where name != 'CHN'; #或者<> desc select * from city where countrycode not in ('CHN','USA'); #注意:生产中几乎是没有这种需求的。尽可能避免
须要扫描整个索引树,获取到想要数据,比ALL性能好,顺序IO,能够减小回表查询
mysql> desc city; +-------------+----------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-------------+----------+------+-----+---------+----------------+ | ID | int(11) | NO | PRI | NULL | auto_increment | | Name | char(35) | NO | | | | | CountryCode | char(3) | NO | MUL | | | | District | char(20) | NO | | | | | Population | int(11) | NO | | 0 | | +-------------+----------+------+-----+---------+----------------+ mysql> desc select CountryCode from city; +----+-------------+-------+------------+-------+---------------+-------------+---------+------+------+----------+-------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-------+------------+-------+---------------+-------------+---------+------+------+----------+-------------+ | 1 | SIMPLE | city | NULL | index | NULL | CountryCode | 3 | NULL | 4188 | 100.00 | Using index | +----+-------------+-------+------------+-------+---------------+-------------+---------+------+------+----------+-------------+
> < >= <= in or like 'CH%' between and --------------------------------------------------- 注意: B+树额外优化了 > < >= <= between and like 'CH%' in or没法享受B+树的额外优化,能够用union all来替代
mysql> desc select * from city where id<10; +----+-------------+-------+------------+-------+---------------+---------+---------+------+------+----------+-------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-------+------------+-------+---------------+---------+---------+------+------+----------+-------------+ | 1 | SIMPLE | city | NULL | range | PRIMARY | PRIMARY | 4 | NULL | 9 | 100.00 | Using where | +----+-------------+-------+------------+-------+---------------+---------+---------+------+------+----------+-------------+ mysql> desc select * from city where countrycode in ('CHN','USA'); +----+-------------+-------+------------+-------+---------------+-------------+---------+------+------+----------+-----------------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-------+------------+-------+---------------+-------------+---------+------+------+----------+-----------------------+ | 1 | SIMPLE | city | NULL | range | CountryCode | CountryCode | 3 | NULL | 637 | 100.00 | Using index condition | +----+-------------+-------+------------+-------+---------------+-------------+---------+------+------+----------+-----------------------+ mysql> desc select * from city where countrycode like 'CH%'; +----+-------------+-------+------------+-------+---------------+-------------+---------+------+------+----------+-----------------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-------+------------+-------+---------------+-------------+---------+------+------+----------+-----------------------+ | 1 | SIMPLE | city | NULL | range | CountryCode | CountryCode | 3 | NULL | 397 | 100.00 | Using index condition | +----+-------------+-------+------------+-------+---------------+-------------+---------+------+------+----------+-----------------------+
mysql> desc select * from city where countrycode in ('CHN','USA'); +----+-------------+-------+------------+-------+---------------+-------------+---------+------+------+----------+-----------------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-------+------------+-------+---------------+-------------+---------+------+------+----------+-----------------------+ | 1 | SIMPLE | city | NULL | range | CountryCode | CountryCode | 3 | NULL | 637 | 100.00 | Using index condition | +----+-------------+-------+------------+-------+---------------+-------------+---------+------+------+----------+-----------------------+ mysql> desc select * from city where countrycode='CHN' union all select * from city where countrycode='USA'; +----+-------------+-------+------------+------+---------------+-------------+---------+-------+------+----------+-------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-------+------------+------+---------------+-------------+---------+-------+------+----------+-------+ | 1 | PRIMARY | city | NULL | ref | CountryCode | CountryCode | 3 | const | 363 | 100.00 | NULL | | 2 | UNION | city | NULL | ref | CountryCode | CountryCode | 3 | const | 274 | 100.00 | NULL | +----+-------------+-------+------------+------+---------------+-------------+---------+-------+------+----------+-------+
mysql> desc select * from city where countrycode = 'CHN'; +----+-------------+-------+------------+------+---------------+-------------+---------+-------+------+----------+-------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-------+------------+------+---------------+-------------+---------+-------+------+----------+-------+ | 1 | SIMPLE | city | NULL | ref | CountryCode | CountryCode | 3 | const | 363 | 100.00 | NULL | +----+-------------+-------+------------+------+---------------+-------------+---------+-------+------+----------+-------+
多表链接的表,On的条件是主键或惟一键
主键或惟一键的等值查询
mysql> desc select * from city where id=10; +----+-------------+-------+------------+-------+---------------+---------+---------+-------+------+----------+-------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-------+------------+-------+---------------+---------+---------+-------+------+----------+-------+ | 1 | SIMPLE | city | NULL | const | PRIMARY | PRIMARY | 4 | const | 1 | 100.00 | NULL | +----+-------------+-------+------------+-------+---------------+---------+---------+-------+------+----------+-------+
索引中扫描不到这个数据
mysql> desc select * from city where id=5000; #id=5000不存在 +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+--------------------------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+--------------------------------+ | 1 | SIMPLE | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | no matching row in const table | +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+--------------------------------+
Extra字段:Using filesort #出现说明有问题,要优化 desc select * from city where countrycode='CHN' order by population desc limit 10; #contrycode上有索引,但population上是没有索引的 mysql> desc select * from city where countrycode='CHN' order by population desc limit 10; +----+-------------+-------+------------+------+---------------+-------------+---------+-------+------+----------+---------------------------------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-------+------------+------+---------------+-------------+---------+-------+------+----------+---------------------------------------+ | 1 | SIMPLE | city | NULL | ref | CountryCode | CountryCode | 3 | const | 363 | 100.00 | Using index condition; Using filesort | +----+-------------+-------+------------+------+---------------+-------------+---------+-------+------+----------+---------------------------------------+ #解决思路: 索引能够减小排序,能够很大程度减小CPU时间 辅助索引 应用顺序(优化器选择的) 若是查询条件:符合覆盖索引的顺序时,优先选择覆盖索引 不符合顺序,优先会走where条件的索引 #解决方法:能够在countrycode和population上创建联合索引 mysql> alter table city add index idx_po(countrycode,population); mysql> desc select * from city where countrycode='CHN' order by population limit 10; +----+-------------+-------+------------+------+--------------------+--------+---------+-------+------+----------+-----------------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-------+------------+------+--------------------+--------+---------+-------+------+----------+-----------------------+ | 1 | SIMPLE | city | NULL | ref | CountryCode,idx_po | idx_po | 3 | const | 363 | 100.00 | Using index condition | +----+-------------+-------+------------+------+--------------------+--------+---------+-------+------+----------+-----------------------+
面试:咱们公司业务慢,请你从数据库的角度分析缘由? mysql出现性能问题,总结有两种状况: (1)应急性的慢:忽然夯住 应急状况:数据库hang(卡了,资源耗尽) 处理过程: (1)show processlist; #获取到致使数据库hang住的语句 (2)explain #分析SQL的执行计划,有没有走索引,索引的类型状况 (3)建索引,改语句 (2)一段时间慢(持续性的): (1)记录慢日志slowlog,分析slowlog (2)explain 分析SQL的执行计划,有没有走索引,索引的类型状况 (3)建索引,改语句
mysqlslap工具介绍 mysqlslap来自于mariadb包,测试的过程默认生成一个mysqlslap的schema,生成测试表t1,查询和插入测试数据,mysqlslap库自动生成,若是已经存在则先删除。用--only-print来打印实际的测试过程,整个测试完成后不会在数据库中留下痕迹。 经常使用选项: --auto-generate-sql, -a 自动生成测试表和数据,表示用mysqlslap工具本身生成的SQL脚原本测试并发压力 --auto-generate-sql-load-type=type 测试语句的类型。表明要测试的环境是读操做仍是写操做仍是二者混合的。取值包括:read,key,write,update和mixed(默认) --auto-generate-sql-add-auto-increment 表明对生成的表自动添加auto_increment列,从5.1.18版本开始支持 --number-char-cols=N, -x N 自动生成的测试表中包含多少个字符类型的列,默认1 --number-int-cols=N, -y N 自动生成的测试表中包含多少个数字类型的列,默认1 --number-of-queries=N 总的测试查询次数(并发客户数×每客户查询次数) --query=name,-q 使用自定义脚本执行测试,例如能够调用自定义的存储过程或者sql语句来执行测试 --create-schema 表明自定义的测试库名称,测试的schema,MySQL中schema也就是database --commint=N 多少条DML后提交一次 --compress, -C 如服务器和客户端都支持压缩,则压缩信息 --concurrency=N, -c N 表示并发量,即模拟多少个客户端同时执行select;可指定多个值,以逗号或者--delimiter参数指定值作为分隔符 --engine=engine_name, -e engine_name 表明要测试的引擎,能够有多个,用分隔符隔开 --iterations=N, -i N 测试执行的迭代次数,表明要在不一样并发环境下,各自运行测试多少次 --only-print 只打印测试语句而不实际执行 --detach=N 执行N条语句后断开重连 --debug-info, -T 打印内存和CPU的相关信息 测试示例: 1)单线程测试 [root@centos7 ~]# mysqlslap -a -uroot -p Enter password: Benchmark Average number of seconds to run all queries: 0.004 seconds Minimum number of seconds to run all queries: 0.004 seconds Maximum number of seconds to run all queries: 0.004 seconds Number of clients running queries: 1 Average number of queries per client: 0 2)多线程测试,使用--concurrency来模拟并发链接 [root@centos7 ~]# mysqlslap -uroot -p -a -c 500 Enter password: Benchmark Average number of seconds to run all queries: 3.384 seconds Minimum number of seconds to run all queries: 3.384 seconds Maximum number of seconds to run all queries: 3.384 seconds Number of clients running queries: 500 Average number of queries per client: 0 3)同时测试不一样的存储引擎的性能进行对比 [root@centos7 ~]# mysqlslap -uroot -p -a --concurrency=500 --number-of-queries 1000 --iterations=5 --engine=myisam,innodb --debug-info Enter password: Benchmark Running for engine myisam Average number of seconds to run all queries: 0.192 seconds Minimum number of seconds to run all queries: 0.187 seconds Maximum number of seconds to run all queries: 0.202 seconds Number of clients running queries: 500 Average number of queries per client: 2 Benchmark Running for engine innodb Average number of seconds to run all queries: 0.355 seconds Minimum number of seconds to run all queries: 0.350 seconds Maximum number of seconds to run all queries: 0.364 seconds Number of clients running queries: 500 Average number of queries per client: 2 User time 0.33, System time 0.58 Maximum resident set size 22892, Integral resident set size 0 Non-physical pagefaults 46012, Physical pagefaults 0, Swaps 0 Blocks in 0 out 0, Messages in 0 out 0, Signals 0 Voluntary context switches 31896, Involuntary context switches 0 4)执行一次测试,分别500和1000个并发,执行5000次总查询 [root@centos7 ~]# mysqlslap -uroot -p -a --concurrency=500,1000 --number-of-queries 5000 --debug-info Enter password: Benchmark Average number of seconds to run all queries: 3.378 seconds Minimum number of seconds to run all queries: 3.378 seconds Maximum number of seconds to run all queries: 3.378 seconds Number of clients running queries: 500 Average number of queries per client: 10 Benchmark Average number of seconds to run all queries: 3.101 seconds Minimum number of seconds to run all queries: 3.101 seconds Maximum number of seconds to run all queries: 3.101 seconds Number of clients running queries: 1000 Average number of queries per client: 5 User time 0.84, System time 0.64 Maximum resident set size 83068, Integral resident set size 0 Non-physical pagefaults 139977, Physical pagefaults 0, Swaps 0 Blocks in 0 out 0, Messages in 0 out 0, Signals 0 Voluntary context switches 31524, Involuntary context switches 3 5)迭代测试 [root@centos7 ~]# mysqlslap -uroot -p -a --concurrency=500 --number-of-queries 5000 --iterations=5 --debug-info Enter password: Benchmark Average number of seconds to run all queries: 3.307 seconds Minimum number of seconds to run all queries: 3.184 seconds Maximum number of seconds to run all queries: 3.421 seconds Number of clients running queries: 500 Average number of queries per client: 10 User time 2.18, System time 1.58 Maximum resident set size 74872, Integral resident set size 0 Non-physical pagefaults 327732, Physical pagefaults 0, Swaps 0 Blocks in 0 out 0, Messages in 0 out 0, Signals 0 Voluntary context switches 73904, Involuntary context switches 3
1)模拟数据库数据
drop database oldboy; create database oldboy charset utf8;
2)建立一个t1的表,而后导入50万行数据
[root@db01 ~]# vim slap.sh #!/bin/bash HOSTNAME="localhost" PORT="3306" USERNAME="root" PASSWORD="1" DBNAME="oldboy" TABLENAME="t1" #create database mysql -h ${HOSTNAME} -P${PORT} -u${USERNAME} -p${PASSWORD} -e "drop database if exists ${DBNAME}" create_db_sql="create database if not exists ${DBNAME}" mysql -h ${HOSTNAME} -P${PORT} -u${USERNAME} -p${PASSWORD} -e "${create_db_sql}" #create table create_table_sql="create table if not exists ${TABLENAME}(stuid int not null primary key,stuname varchar(20) not null,stusex char(1) not null,cardid varchar(20) not null,birthday datetime,entertime datetime,address varchar(100)default null)" mysql -h ${HOSTNAME} -P${PORT} -u${USERNAME} -p${PASSWORD} ${DBNAME} -e "${create_table_sql}" #insert data to table i="1" while [ $i -le 500000 ] do insert_sql="insert into ${TABLENAME} values($i,'alexsb_$i','1','110011198809163418','1990-05-16','2017-09-13','oldboyedu')" mysql -h ${HOSTNAME} -P${PORT} -u${USERNAME} -p${PASSWORD} ${DBNAME} -e "${insert_sql}" let i++ done #select data select_sql="select count(*) from ${TABLENAME}" mysql -h ${HOSTNAME} -P${PORT} -u${USERNAME} -p${PASSWORD} ${DBNAME} -e "${select_sql}" 执行脚本: sh slap.sh 或者直接source drop database oldboy; source /root/oldboy.sql
3)检查数据可用性
mysql -uroot -p select count(*) from oldboy.t1;
4)使用mysqlslap来进行压力测试
mysqlslap --defaults-file=/etc/my.cnf \ --concurrency=100 --iterations=1 --create-schema='oldboy' \ --query="select * from oldboy.t1 where stuname='alexsb_100'" engine=innodb \ --number-of-queries=2000 -uroot -pmysql -verbose
没创建索引以前:
在查询条件列上创建索引:alter table t1 add index idx_name(stuname);
1)tpcc
2)sysbench
主要根据公司的业务来创建合适的索引
为了使索引的使用效率更高,在建立索引时,必须考虑在哪些字段上建立索引和建立什么类型的索引。
1)建表时必定要有主键,通常是个无关列(必须)
2)选择惟一键索引
惟一性索引的值是惟一的,能够更快速的经过该索引来肯定某条记录。 #优化方案: (1) 若是非得使用重复值较多的列做为查询条件(例如:男女),能够将表逻辑拆分 (2) 能够将此列和其余的查询类,作联和索引 #如何判断索引列有多少是惟一值? select count(*) from world.city; select count(distinct countrycode) from world.city; select count(distinct countrycode,population ) from world.city;
3)为常常须要where 、ORDER BY、GROUP BY,join on等操做的字段创建索引,排序操做会浪费不少时间。注:若是常常做为条件的列,重复值特别多,能够创建联合索引
4)使用前缀索引。若是索引字段的值很长,最好使用值的前缀来索引。
5)限制索引的数目
索引的数目不是越多越好。可能会产生的问题: (1) 每一个索引都须要占用磁盘空间,索引越多,须要的磁盘空间就越大。 (2) 修改表时,对索引的重构和更新很麻烦。越多的索引,会使更新表变得很浪费时间。 (3) 优化器的负担会很重,有可能会影响到优化器的选择.
6)删除再也不使用或者不多使用的索引(使用percona toolkit)
表中的数据被大量更新,或者数据的使用方式被改变后,原有的一些索引可能再也不须要。数据库管理 员应当按期找出这些索引,将它们删除,从而减小索引对更新操做的影响。
7)大表加索引,要在业务不繁忙期间操做
8)尽可能少在常常更新值的列上建索引
创建索引原则总结:
(1) 必需要有主键,若是没有能够作为主键条件的列,建立无关列 (2) 常常作为where条件列 order by group by join on, distinct 的条件(业务:产品功能+用户行为) (3) 最好使用惟一值多的列做为索引,若是索引列重复值较多,能够考虑使用联合索引 (4) 列值长度较长的索引列,咱们建议使用前缀索引. (5) 下降索引条目,一方面不要建立没用索引,不常使用的索引清理,使用percona toolkit工具 (6) 索引维护要避开业务繁忙期
1)没有查询条件,或者查询条件没有创建索引
select * from tab; #全表扫描 select * from tab where 1=1;
在业务数据库中,特别是数据量比较大的表,是没有全表扫描这种需求。
(1)select * from tab; SQL改写成如下语句: selec * from tab order by price limit 10 ; #须要在price列上创建索引 (2)select * from tab where name='zhangsan' #name列没有索引 改为以下语句: 一、换成有索引的列做为查询条件 二、将name列创建索引
2)查询的结果集,超过了总数行数25%,优化器默认没有必要走索引
解决方法: 一、若是业务容许,可使用limit控制。 二、尽可能不要在mysql存放这个数据了,能够放到redis里面
3)索引自己失效,统计数据不真实
索引有自我维护的能力。对于表内容变化比较频繁的状况下,有可能会出现索引失效。通常是删除重建
4)查询条件使用函数在索引列上,或者对索引列进行运算,运算包括(+,-,*,/,! 等)
错误的例子:select * from test where id-1=9; 正确的例子:select * from test where id=10; 在索引列上使用算术运算,函数运算,子查询时,可能不会走索引
5)隐式转换致使索引失效
mysql> alter table tab add index inx_tel(telnum); mysql> desc tab; +--------+-------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +--------+-------------+------+-----+---------+-------+ | id | int(11) | YES | | NULL | | | name | varchar(20) | YES | | NULL | | | telnum | varchar(20) | YES | MUL | NULL | | #字段类型是varchar,同时创建了索引 +--------+-------------+------+-----+---------+-------+ mysql> select * from tab where telnum='1333333'; #查询条件是字符串,走索引 +------+------+---------+ | id | name | telnum | +------+------+---------+ | 1 | a | 1333333 | +------+------+---------+ mysql> select * from tab where telnum=1333333; #查询条件是数字,隐式转换为字符串 +------+------+---------+ | id | name | telnum | +------+------+---------+ | 1 | a | 1333333 | +------+------+---------+ mysql> explain select * from tab where telnum='1333333'; +----+-------------+-------+------+---------------+---------+---------+-------+------+-----------------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+------+---------------+---------+---------+-------+------+-----------------------+ | 1 | SIMPLE | tab | ref | inx_tel | inx_tel | 63 | const | 1 | Using index condition | +----+-------------+-------+------+---------------+---------+---------+-------+------+-----------------------+ mysql> explain select * from tab where telnum=1333333; +----+-------------+-------+------+---------------+------+---------+------+------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+------+---------------+------+---------+------+------+-------------+ | 1 | SIMPLE | tab | ALL | inx_tel | NULL | NULL | NULL | 2 | Using where | +----+-------------+-------+------+---------------+------+---------+------+------+-------------+
6)<> ,not in 不走索引
EXPLAIN SELECT * FROM teltab WHERE telnum <> '110'; EXPLAIN SELECT * FROM teltab WHERE telnum NOT IN ('110','119'); 注意: 1. 单独的>,<,in 有可能走,也有可能不走,和结果集有关,尽可能结合业务添加limit 2. or或in 尽可能改为union EXPLAIN SELECT * FROM teltab WHERE telnum IN ('110','119'); 改写成: EXPLAIN SELECT * FROM teltab WHERE telnum='110' UNION ALL SELECT * FROM teltab WHERE telnum='119'
7)like "%_" 百分号在最前面不走
EXPLAIN SELECT * FROM teltab WHERE telnum LIKE '31%' #走range索引扫描 EXPLAIN SELECT * FROM teltab WHERE telnum LIKE '%110' #不走索引 %linux%类的搜索需求,可使用elasticsearch+mongodb 专门作搜索服务的数据库产品
8)单独引用联合索引里非第一位置的索引列.做为条件查询时不走索引
idx_a_b_c(a,b,c) #创建的联合索引 走索引的状况: where a b c where a b where a ============ 部分走索引 where a c where a c b ============ 不走索引 where c where b where bc where cb where ca where cba