为搜索字段建立索引
1.创建索引
ALTER TABLE 用来创建普通索引、唯一索引、主键索引和全文索引 ALTER TABLE table_name ADD INDEX index_name (column_list); ALTER TABLE table_name ADD UNIQUE (column_list); ALTER TABLE table_name ADD PRIMARY KEY (column_list); ALTER TABLE table_name ADD FULLTEXT (column_list);
其中table_name是要增加索引名的表名,column_list指出对哪些列列进行索引,多列时各列之间使用半角逗号隔开。索引名index_name是可选的,如果不指定索引名称,MySQL将根据第一个索引列自动指定索引名称,另外,ALTER TABLE允许在单个语句中更改多个表,因此可以在同时创建多个索引。
CREATE INDEX index_name ON table_name (column_list); CREATE UNIQUE index_name ON table_name (column_list); CREATE FULLTEXT index_name ON table_name (column_list);
table_name、index_name和column_list具有与ALTER TABLE语句中相同的含义,索引名必须指定。另外,不能用CREATE INDEX语句创建PRIMARY KEY索引。
2.索引类型
ALTER TABLE article ADD FULLTEXT ('title', 'content'); 在进行检索时就需要使用如下的语法进行检索: SELECT * FROM article WHERE MATCH('title', 'content') AGAINST ('查询字符串');
3.组合索引
where a=3 and b=45 and c=5 .... #这种三个索引顺序使用中间没有断点,全部发挥作用; where a=3 and c=5... #这种情况下b就是断点,a发挥了效果,c没有效果 where b=3 and c=4... #这种情况下a就是断点,在a后面的索引都没有发挥作用,这种写法联合索引没有发挥任何效果; where b=45 and a=3 and c=5 .... #这个跟第一个一样,全部发挥作用,abc只要用上了就行,跟写的顺序无关
(a,b,c) 三个列上加了联合索引(是联合索引 不是在每个列上单独加索引)而是建立了a,(a,b),(a,b,c)三个索引,另外(a,b,c)多列索引和 (a,c,b)是不一样的。
具体实例可以说明:
(0) select * from mytable where a=3 and b=5 and c=4; #abc三个索引都在where条件里面用到了,而且都发挥了作用 (1) select * from mytable where c=4 and b=6 and a=3; #这条语句为了说明 组合索引与在SQL中的位置先后无关,where里面的条件顺序在查询之前会被mysql自动优化,效果跟上一句一样 (2) select * from mytable where a=3 and c=7; #a用到索引,b没有用,所以c是没有用到索引效果的 (3) select * from mytable where a=3 and b>7 and c=3; #a用到了,b也用到了,c没有用到,这个地方b是范围值,也算断点,只不过自身用到了索引 (4) select * from mytable where b=3 and c=4; #因为a索引没有使用,所以这里 bc都没有用上索引效果 (5) select * from mytable where a>4 and b=7 and c=9; #a用到了 b没有使用,c没有使用 (6) select * from mytable where a=3 order by b; #a用到了索引,b在结果排序中也用到了索引的效果,前面说了,a下面任意一段的b是排好序的 (7) select * from mytable where a=3 order by c; #a用到了索引,但是这个地方c没有发挥排序效果,因为中间断点了,使用 explain 可以看到 filesort (8) select * from mytable where b=3 order by a; #b没有用到索引,排序中a也没有发挥索引效果
注意:在查询时,MYSQL只能使用一个索引,如果建立的是多个单列的普通索引,在查询时会根据查询的索引字段,
从中选择一个限制最严格的单例索引进行查询。别的索引都不会生效。
不能使用索引的情况
SELECT * FROM tab_name WHERE index_column LIKE 'abc%'; #索引是有效的 SELECT * FROM tab_name WHERE index_column LIKE '%abc'; #索引是无效的SELECT * FROM tab_name WHERE index_column LIKE '%abc%'; #索引是无效的
当检索的字段内容比较大而且检索内容前后部分都不确定的情况下,可以改为全文索引,并使用特定的检索方式。
既然字符串以通配符(%)开始就不会走索引。那么如果类似 like "%xxx" 的sql,如何走索引呢?
基于REVERSE()函数来创建一个函数索引。
1、准备数据:
CREATE TABLE jka AS SELECT ROWNUM id, dbms_random.string('x',10) v FROM dual CONNECT BY LEVEL <= 10000;
2、创建原始索引:
CREATE INDEX jka_normal ON jka (v);
3、以下SQL基于jka_normal索引走范围扫描:
SELECT * FROM jka WHERE v LIKE 'ABC%';
4、但是下面的SQL将走全表扫描(不会使用索引):
SELECT * FROM jka WHERE v LIKE '%ABC';
5、现在,创建一个函数索引(不要与反向索引[REVERSE INDEX]混淆):
CREATE INDEX jka_reverse ON jka(REVERSE(v));
6、下面的SQL将基于jka_reverse索引走范围扫描:
SELECT * FROM jka WHERE REVERSE(v) LIKE REVERSE('%ABC');