Mysql study concluded (7) - MySql indexing works with Compendium

I. Introduction Index

     Index value in the database is one or more columns in the table is sorted a configuration. In a relational database, the index is a database structure associated with a table, it can make the table corresponds to the SQL statement executed faster. The role of the index is equivalent to the book catalog, you can quickly find what you need based on the directory page. When a table in a large number of records, to query a table, the first way is to search for information search the entire table, all records eleven is taken out one by one and compare the query, then returns records meet the conditions, so do consume a large amount of time database system, and cause a lot of disk I / O operations; the second is the establishment of the index in the table, then find the index values match the query in the index, and finally through ROWID stored in the index (equivalent to page) table quickly find the corresponding record.
        It is a single index, the physical database structure, which is a logical pointer to a list of data pages set in a table or a plurality of column values and the corresponding points in the table identifies the physical values. Index provides a pointer pointing to the data value stored in the specified column of the table, and then sort these pointers you specified sort order. Database using the index and the way you use the book in a way very similar to the index: it searches the index to find a particular value, then the clockwise find the line containing the value. Can be created in the "Indexes / Keys" property page selected tables in a database diagram, edit or delete each index type. When applied to hold the index in the appended table, diagram, or save the table is located, the index will be stored in the database.

Mysql Index Overview

        All MySQL column types can be indexed. Using the index of the relevant columns is the best way to improve the performance of SELECT operations. The maximum number of indexes per table index and the maximum length defined in accordance with the storage engine. All storage engine supports each table index of at least 16, at least a total length of 256 bytes index. Most storage engines have higher limits.

        In MySQL 5.1, and for MyISAM InnoDB tables, prefixes up to 1000 bytes long. Please note that limits the prefix bytes shall be measured, and the prefix length of the CREATE TABLE statement is interpreted as the number of characters. When specifying a prefix length using multi-byte character set columns must be considered.

        You can also create FULLTEXT indexes. The index can be used for full-text search. Only the MyISAM storage engine supports FULLTEXT indexes and only for CHAR, VARCHAR and TEXT columns. The index is always for the entire column, does not support partial (prefix) index. You can also create indexes for spatial data types. Only the MyISAM storage engine supports spatial types. Spatial index use R- tree. By default, MEMORY (HEAP) storage engine uses hash indexes, but also supports the B- tree index.

btree index and hash index

         For BTREE and HASH index, when =, <=>, IN, IS NULL or IS NOT NULL operator, comparing the relationship between the key elements and a constant value corresponding to a range of conditions. Hash index There are other features: they are only used for the equation or = <=> comparison operator (but soon). Optimization can not use the hash index to speed up ORDER BY operations. (Such index can not be used to search for the next entry in order). MySQL can not determine the approximate number of rows (this is the range of the optimizer used to determine which index) between the two values. If you change a MyISAM table index hash- MEMORY table, it will affect some queries. Only use keywords to search the entire line. (With a B- tree index, any leftmost prefix of the keywords used to find the line).

        For BTREE index, when using>, <,> =, <=, BETWEEN,! =, Or <>, or when the operator, the more critical elements of constant values ​​for the LIKE 'pattern' (where 'pattern' does not start with a wildcard) a corresponding relationship range condition. "Constant value" means: constant string query, the same coupling system const or columns in the table, the results of uncorrelated subquery, completely removed from the subexpression consisting of the front type expression.

下面是一些WHERE子句中有范围条件的查询的例子。

下列范围查询适用于 btree索引和hash索引:

SELECT * FROM t1     WHERE key_col = 1     OR key_col IN (15,18,20);
 下列范围查询适用于btree索引
SELECT * FROM t1     WHERE key_col > 1     AND key_col < 10;
  SELECT * FROM t1     WHERE key_col LIKE 'ab%'     OR key_col BETWEEN 'bar' AND 'foo';

Mysql如何使用索引

          索引用于快速找出在某个列中有一特定值的行。不使用索引,MySQL必须从第1条记录开始然后读完整个表直到找出相关的行。表越大,花费的时间越多。如果表中查询的列有一个索引,MySQL能快速到达一个位置去搜寻到数据文件的中间,没有必要看所有数据。如果一个表有1000行,这比顺序读取至少快100倍。注意如果你需要访问大部分行,顺序读取要快得多,因为此时我们避免磁盘搜索。

大多数MySQL索引(PRIMARY KEY、UNIQUE、INDEX和FULLTEXT)在B树中存储。只是空间列类型的索引使用R-树,并且MEMORY表还支持hash索引。


二、使用方法

首先先创建一个表:

[sql]  view plain copy
  1. CREATE TABLE  
  2.     t_student  
  3.     (  
  4.         STU_ID INT NOT NULL,  
  5.         STU_NAME CHAR(10) NOT NULL,  
  6.         STU_CLASS INT NOT NULL,  
  7.         STU_SEX CHAR(2) NOT NULL,  
  8.         STU_AGE INT NOT NULL,  
  9.         PRIMARY KEY (STU_ID)  
  10.     )  
  11.     ENGINE=InnoDB DEFAULT CHARSET=utf8;  

1.1 普通索引

创建索引
这是最基本的索引,它没有任何限制。它有以下几种创建方式:

[sql]  view plain copy
  1. CREATE INDEX index_id  ON t_student(STU_ID);   



如果是CHAR,VARCHAR类型,length可以小于字段实际长度;如果是BLOB和TEXT类型,必须指定 length。
修改表结构

[java]  view plain copy
  1. ALTER TABLE t_student ADD INDEX  index_name(STU_NAME(4)) ;  


创建表的时候直接指定

[sql]  view plain copy
  1. CREATE TABLE  
  2.     t_student1  
  3.     (  
  4.         STU_ID INT NOT NULL,  
  5.         STU_NAME CHAR(10) NOT NULL,  
  6.         STU_CLASS INT NOT NULL,  
  7.         STU_SEX CHAR(2) NOT NULL,  
  8.         STU_AGE INT NOT NULL,  
  9.         PRIMARY KEY (STU_ID),  
  10.         INDEX index_name (STU_NAME(5))  
  11.     )  
  12.     ENGINE=InnoDB DEFAULT CHARSET=utf8;  


删除索引的语法
[sql]  view plain copy
  1. DROP INDEX index_id  ON t_student;  
  2. DROP INDEX index_name  ON t_student;  

结果

1.2、唯一索引

       主键就是唯一索引的一种,主键要求建表时指定,一般用auto_increment列,关键字是primary key。它与前面的普通索引类似,不同的就是:索引列的值必须唯一,但允许有空值。如果是组合索引,则列值的组合必须唯一。它有以下几种创建方式:
创建索引


[sql]  view plain copy
  1. CREATE UNIQUE INDEX indexName ON mytable(username(length))   
修改表结构
[sql]  view plain copy
  1. ALTER mytable ADD UNIQUE [indexName] ON (username(length))   
创建表的时候直接指定
[java]  view plain copy
  1. CREATE TABLE mytable(  
  2. ID INT NOT NULL,  
  3. username VARCHAR(16) NOT NULL,  
  4. UNIQUE [indexName] (username(length))  
  5. );   

1. 3、多列索引

创建索引

[sql]  view plain copy
  1. CREATE  INDEX indexName ON mytable(username1(length),username2(length))   

CREATE INDEX index_age_aex ON t_student(STU_AGE,STU_SEX);


修改表结构

[sql]  view plain copy
  1. ALTER mytable ADD  [indexName] ON (username1(length),username2(length))   
创建表的时候直接指定
[java]  view plain copy
  1. CREATE TABLE mytable(  
  2. ID INT NOT NULL,  
  3. username VARCHAR(16) NOT NULL,  
  4. INDEX [indexName] (username1(length),username2(length))  
  5. );   
多列索引的一个优点,它通过称为最左前缀(Leftmost Prefixing)的概念体现出来。继续考虑前面的例子,现在我们有一个firstname、lastname、age列上的多列索引,我们称这个索引为fname_lname_age。当搜索条件是以下各种列的组合时,MySQL将使用fname_lname_age索引: 
firstname,lastname,age
firstname,lastname
firstname
从另一方面理解,它相当于我们创建了(firstname,lastname,age)、(firstname,lastname)以及(firstname)这些列组合上的索引。下面这些查询都能够使用这个fname_lname_age索引: 
Select peopleid FROM people Where firstname='Mike' AND lastname='Sullivan' AND age='17'; 
Select peopleid FROM people Where firstname='Mike' AND lastname='Sullivan'; 
Select peopleid FROM people Where firstname='Mike'; 
下面这些查询不能够使用这个fname_lname_age索引: 
Select peopleid FROM people Where lastname='Sullivan'; 
Select peopleid FROM people Where age='17'; 
Select peopleid FROM people Where lastname='Sullivan' AND age='17'; 


1.4、全文索引

        全文索引(也称全文检索)是目前搜索引擎使用的一种关键技术。它能够利用「分词技术「等多种算法智能分析出文本文字中关键字词的频率及重要性,然后按照一定的算法规则智能地筛选出我们想要的搜索结果。在这里,我们就不追根究底其底层实现原理了,现在我们来看看在MySQL中如何创建并使用全文索引。
        在MySQL中,创建全文索引相对比较简单。例如,我们有一个文章表(article),其中有主键ID(id)、文章标题(title)、文章内容(content)三个字段。现在我们希望能够在title和content两个列上创建全文索引,article表及全文索引的创建SQL语句如下:
--创建article表

[sql]  view plain copy
  1. CREATE TABLE article (  
  2.  id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,   
  3.  title VARCHAR(200),  
  4.  content TEXT,  
  5.  FULLTEXT (title, content)  
  6.  )ENGINE=MyISAM DEFAULT CHARSET=utf8;  
 

看看索引

上面就是在创建表的同时建立全文索引的SQL示例。此外,如果我们想要给已经存在的表的指定字段创建全文索引,同样以article表为例,我们可以使用如下SQL语句进行创建:
--给现有的article表的title和content字段创建全文索引
--索引名称为fulltext_article

[sql]  view plain copy
  1. ALTER TABLE article ADD FULLTEXT INDEX fulltext_article (title, content)  
     在MySQL中创建全文索引之后,现在就该了解如何使用了。我们必须使用特有的语法才能使用全文索引进行查询。例如,我们想要在article表的title和content列中全文检索指定的查询字符串,可以如下编写SQL语句:
[sql]  view plain copy
  1. SELECT * FROM article WHERE MATCH(title, content) AGAINST ('查询字符串');  

注意事项

搜索必须在类型为fulltext的索引列上,match中指定的列必须在fulltext中指定过
仅能应用在表引擎为MyIsam类型的表中(MySQL 5.6以后也可以用在Innodb表引擎中了)
仅能再char、varchar、text类型的列上面创建全文索引
像普通索引一样,可以在定义表时指定,也可以在创建表后添加或者修改
对于一个大数量级记录插入,向没有索引的表中插入数据后创建索引比向有索引的数据表中插入的过程要快很多
搜索字符串必须是一个常量字符串,不能是表的列名
在搜索记录的选择性超过50%的时候,认为没有匹配(只在自然搜索中限制)

1.5、验证是否使用是索引

些处接1.3.这里可以接上面多列索引,在这里我已经加了一些数据进去,如下


可以用语句 EXPLAIN SELECT * FROM t_student WHERE STU_AGE = 12;来验证是否使用到了索引

下面说明用到了索引


如果没用到索引,结果应该是如下:


上面只是验证是否使用了索引,接下来看来看看使用了索引和没使用索引的结果:

使用了索引的结果:(注意,这里添加了CREATE INDEX index_age_aex ON t_student(STU_AGE,STU_SEX);)

结果按SEX和AGE来进行排序


把索引给删除了,执行同样的语句:

结果直接按ID进行排序


1.6、使用ALTER 命令添加和删除索引

有四种方式来添加数据表的索引:
[sql]  view plain copy
  1. ALTER TABLE tbl_name ADD PRIMARY KEY (column_list): 该语句添加一个主键,这意味着索引值必须是唯一的,且不能为NULL。  
  2. ALTER TABLE tbl_name ADD UNIQUE index_name (column_list): 这条语句创建索引的值必须是唯一的(除了NULL外,NULL可能会出现多次)。  
  3. ALTER TABLE tbl_name ADD INDEX index_name (column_list): 添加普通索引,索引值可出现多次。  
  4. ALTER TABLE tbl_name ADD FULLTEXT index_name (column_list):该语句指定了索引为 FULLTEXT ,用于全文索引。  
以下实例为在表中添加索引。
[sql]  view plain copy
  1. ALTER TABLE testalter_tbl ADD INDEX (c);  
你还可以在 ALTER 命令中使用 DROP 子句来删除索引。尝试以下实例删除索引:
[sql]  view plain copy
  1. ALTER TABLE testalter_tbl DROP INDEX (c);  
使用 ALTER 命令添加和删除主键
主键只能作用于一个列上,添加主键索引时,你需要确保该主键默认不为空(NOT NULL)。实例如下:

[sql]  view plain copy
  1. ALTER TABLE testalter_tbl MODIFY i INT NOT NULL;  
  2. LTER TABLE testalter_tbl ADD PRIMARY KEY (i);  
你也可以使用 ALTER 命令删除主键:
[sql]  view plain copy
  1. ALTER TABLE testalter_tbl DROP PRIMARY KEY;  
删除指定时只需指定PRIMARY KEY,但在删除索引时,你必须知道索引名。
显示索引信息
你可以使用 SHOW INDEX 命令来列出表中的相关的索引信息。可以通过添加 \G 来格式化输出信息。
尝试以下实例:

[sql]  view plain copy
  1. SHOW INDEX FROM table_name\G  

三、索引的不足之处

上面都在说使用索引的好处,但过多的使用索引将会造成滥用。因此索引也会有它的缺点:

1.虽然索引大大提高了查询速度,同时却会降低更新表的速度,如对表进行INSERT、UPDATE和DELETE。因为更新表时,MySQL不仅要保存数据,还要保存一下索引文件。

2.建立索引会占用磁盘空间的索引文件。一般情况这个问题不太严重,但如果你在一个大表上创建了多种组合索引,索引文件的会膨胀很快。

索引只是提高效率的一个因素,如果你的MySQL有大数据量的表,就需要花时间研究建立最优秀的索引,或优化查询语句。

四、使用索引的注意事项

使用索引时,有以下一些技巧和注意事项:

1.索引不会包含有NULL值的列

只要列中包含有NULL值都将不会被包含在索引中,复合索引中只要有一列含有NULL值,那么这一列对于此复合索引就是无效的。所以我们在数据库设计时不要让字段的默认值为NULL。

2.使用短索引

对串列进行索引,如果可能应该指定一个前缀长度。例如,如果有一个CHAR(255)的列,如果在前10个或20个字符内,多数值是惟一的,那么就不要对整个列进行索引。短索引不仅可以提高查询速度而且可以节省磁盘空间和I/O操作。

3.索引列排序

MySQL查询只使用一个索引,因此如果where子句中已经使用了索引的话,那么order by中的列是不会使用索引的。因此数据库默认排序可以符合要求的情况下不要使用排序操作;尽量不要包含多个列的排序,如果需要最好给这些列创建复合索引。

4.like语句操作

一般情况下不鼓励使用like操作,如果非使用不可,如何使用也是一个问题。like “%aaa%” 不会使用索引而like “aaa%”可以使用索引。

5.不要在列上进行运算

select * from users where YEAR(adddate)<2007;

It will take place on each line operations, which will lead to failure while the index for full table scan, so we can read:

select * from users where adddate<‘2007-01-01';

6. not used and NOT IN <> Operation

Reproduced in: https: //my.oschina.net/zhanghaiyang/blog/606319

Guess you like

Origin blog.csdn.net/weixin_34137799/article/details/92658469