• 数据库索引的使用和优化


    为搜索字段建立索引

    索引不一定就是给主键或者是唯一的字段,如果在表中,有某个字段经常用来做搜索,需要将其建立索引。
    索引的有关操作如下:

    1.创建索引

    在执行CREATE TABLE语句时可以创建索引,也可以单独用CREATE INDEX或ALTER TABLE来为表增加索引。
    1.1> ALTER TABLE
    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允许在单个语句中更改多个表,因此可以在同时创建多个索引。

    1.2> CREATE INDEX
    CREATE INDEX可对表增加普通索引或UNIQUE索引以及全文索引,但是不可以对表增加主键索引
    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.索引类型

    普通索引INDEX:适用于name、email等一般属性
    唯一索引UNIQUE:与普通索引类似,不同的是唯一索引要求索引字段值在表中是唯一的,这一点和主键索引类似,但是不同的是,唯一索引允许有空值
            唯一索引一般适用于身份证号码、用户账号等不允许有重复的属性字段上。
    主键索引:其实就是主键,一般在建表时就指定了,不需要额外添加。
    全文检索:只适用于VARCHAR和Text类型的字段。
    注意:全文索引和普通索引是有很大区别的,如果建立的是普通索引,一般会使用like进行模糊查询,只会对查询内容前一部分有效,即只对前面不使用通配符的查询有效,如果前后都有通配符,普通索引将不会起作用。对于全文索引而言在查询时有自己独特的匹配方式,例如我们在对一篇文章的标题和内容进行全文索引时:
    ALTER TABLE article ADD FULLTEXT ('title', 'content'); 在进行检索时就需要使用如下的语法进行检索:
    SELECT * FROM article WHERE MATCH('title', 'content') AGAINST ('查询字符串');
    在使用全文检索时的注意事项:
    MySql自带的全文索引只能用于数据库引擎为MYISAM的数据表,如果是其他数据引擎,则全文索引不会生效。
    此外,MySql自带的全文索引只能对英文进行全文检索,目前无法对中文进行全文检索。如果需要对包含中文在内的文本数据进行全文检索,我们需要采用Sphinx(斯芬克斯)/Coreseek技术来处理中文。另外使用MySql自带的全文索引时,如果查询字符串的长度过短将无法得到期望的搜索结果。MySql全文索引所能找到的词默认最小长度为4个字符。另外,如果查询的字符串包含停止词,那么该停止词将会被忽略。
     

    3.组合索引

    组合索引又称多列索引,就是建立索引时指定多个字段属性。
    有点类似于字典目录,比如查询 'guo' 这个拼音的字时,首先查找g字母,然后在g的检索范围内查询第二个字母为u的列表,最后在u的范围内查找最后一个字母为o的字。
    比如组合索引(a,b,c),abc都是排好序的,在任意一段a的下面b都是排好序的,任何一段b下面c都是排好序的
    组合索引的生效原则是 :从前往后依次使用生效,如果中间某个索引没有使用,那么断点前面的索引部分起作用,断点后面的索引没有起作用
    造成断点的原因:
    前边的任意一个索引没有参与查询,后边的全部不生效。
    前边的任意一个索引字段参与的是范围查询,后面的不会生效。
    断点跟索引字字段在SQL语句中的位置前后无关,只与是否存在有关。在网上找到了很好的示例:
    比如:
    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只能使用一个索引,如果建立的是多个单列的普通索引,在查询时会根据查询的索引字段,

    从中选择一个限制最严格的单例索引进行查询。别的索引都不会生效

    不能使用索引的情况 

    对于普通索引而言 在使用like进行通配符模糊查询时,如果首尾之间都使用了通配符,索引时无效的。
    假设查询内容的关键词为'abc'
    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');
  • 相关阅读:
    506. 相对排名 Relative Ranks
    500. 单词是否在键盘上的同一行 Keyboard Row
    openstack live migration性能分析
    libvirt/qemu特性之numa
    nova Scheduling 配置
    Specify compute hosts with SSDs
    nova conductor
    osprofiler
    watcher
    stacktach和ceilometer
  • 原文地址:https://www.cnblogs.com/alsf/p/9274851.html
Copyright © 2020-2023  润新知