当前位置: 首页 > 图文教程 > 数据库 > MYSQL > MySql:Mysql优化方案之索引的使用

MYSQL
mysql 常用数据库语句 小练习
MYSQL ERROR 1045 (28000): Access denied for user (using password: YES)问题的解决
mysql 字符集的系统变量说明
MySQL 在触发器里中断记录的插入或更新?
将MySQL数据库移植为PostgreSQL
mysql 操作总结 INSERT和REPLACE
linux mysql忘记密码的多种解决或Access denied for user ''root''@''localhost''
运用mysqldump 工具时需要注意的问题
mysql 优化日记
MySQL 字符串函数大全
mysql 截取指定的两个字符串之间的内容
MySQL 备份还原数据库批处理
mysql 数据库中my.ini的优化 2G内存针对站多 抗压型的设置
Mysql 数字类型转换函数
mysql 动态生成测试数据
mysql 显示SQL语句执行时间的代码
mysql 设置查询缓存
MYSQL explain 执行计划
MySQL 有输入输出参数的存储过程实例
巧用mysql提示符prompt清晰管理数据库的方法

MYSQL 中的 MySql:Mysql优化方案之索引的使用


出处:互联网   整理: 软晨网(RuanChen.com)   发布: 2009-08-14   浏览: 70 ::
收藏到网摘: n/a

数据库性能的好坏和数据库的优化是分不开的,对于大量数据来说,索引更是分布开的,今天小谈数据库的索引,希望对大家有所帮助。

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

 

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

 

字符串自动地压缩前缀和结尾空格。

 

总的来说,按后面的讨论使用索引。本节最后描述hash索引(用于MEMORY)的特征。

 

索引用于下面的操作:

 

·         快速找出匹配一个WHERE子句的行。

 

·         删除行。如果可以在多个索引中进行选择,MySQL通常使用找到最少行的索引。

 

·         当执行联接时,从其它表检索行。

 

·         对具体有索引的列key_col找出MAX()MIN()值。由预处理器进行优化,检查是否对索引中在key_col之前发生所有关键字元素使用了WHERE key_part_# = constant。在这种情况下,MySQL为每个MIN()MAX()表达式执行一次关键字查找,并用常数替换它。如果所有表达式替换为常量,查询立即返回。例如:

 

·                SELECT MIN(key_part2),MAX(key_part2)

·                    FROM tbl_name WHERE key_part1=10;

·         如果对一个可用关键字的最左面的前缀进行了排序或分组(例如,ORDER BY key_part_1,key_part_2),排序或分组一个表。如果所有关键字元素后面有DESC,关键字以倒序被读取。

·         在一些情况中,可以对一个查询进行优化以便不用查询数据行即可以检索值。如果查询只使用来自某个表的数字型并且构成某些关键字的最左面前缀的列,为了更快,可以从索引树检索出值。

 

·                SELECT key_part3 FROM tbl_name

·                    WHERE key_part1=1

假定你执行下面的SELECT语句:

 

mysql> SELECT * FROM tbl_name WHERE col1=val1 AND col2=val2;

如果col1col2上存在一个多列索引,可以直接取出相应行。如果col1col2上存在单列索引,优化器试图通过决定哪个索引将找到更少的行来找出更具限制性的索引并且使用该索引取行。

 

如果表有一个多列索引,优化器可以使用最左面的索引前缀来找出行。例如,如果有一个3列索引(col1,col2,col3),则已经对(col1)(col1,col2)(col1,col2,col3)上的搜索进行了索引。

 

如果列不构成索引最左面的前缀,MySQL不能使用局部索引。假定有下面显示的SELECT语句。

 

 

SELECT * FROM tbl_name WHERE col1=val1;

SELECT * FROM tbl_name WHERE col1=val1 AND col2=val2;

 

SELECT * FROM tbl_name WHERE col2=val2;

SELECT * FROM tbl_name WHERE col2=val2 AND col3=val3;

 

如果 (col1col2col3)有一个索引,只有前2个查询使用索引。第3个和第4个查询确实包括索引的列,但(col2)(col2col3)不是 (col1col2col3)的最左边的前缀。

 

也可以在表达式通过=>>=<<=或者BETWEEN操作符使用B-树索引进行列比较。如果LIKE的参数是一个不以通配符开头的常量字符串,索引也可以用于LIKE比较。例如,下面的SELECT语句使用索引:

 

SELECT * FROM tbl_name WHERE key_col LIKE 'Patrick%';

SELECT * FROM tbl_name WHERE key_col LIKE 'Pat%_ck%';

在第1个语句中,只考虑带'Patrick' <=key_col < 'Patricl'的行。在第2个语句中,只考虑带'Pat' <=key_col < 'Pau'的行。

 

下面的SELECT语句不使用索引:

 

SELECT * FROM tbl_name WHERE key_col LIKE '%Patrick%';

SELECT * FROM tbl_name WHERE key_col LIKE other_col;

在第一条语句中,LIKE值以一个通配符字符开始。在第二条语句中,LIKE值不是一个常数。

 

如果使用... LIKE '%string%'并且string超过3个字符,MySQL使用Turbo Boyer-Moore算法初始化字符串的模式然后使用该模式来更快地进行搜索。

 

如果col_name被索引,使用col_name IS NULL的搜索将使用索引。

 

任何不跨越WHERE子句中的所有AND级的索引不用于优化查询。换句话说,为了能够使用索引,必须在每个AND组中使用索引前缀。

 

下面的WHERE子句使用索引:

 

... WHERE index_part1=1 AND index_part2=2 AND other_column=3

    /* index = 1 OR index = 2 */

... WHERE index=1 OR A=10 AND index=2

    /* optimized like "index_part1='hello'" */

... WHERE index_part1='hello' AND index_part3=5

    /* Can use index on index1 but not on index2 or index3 */

... WHERE index1=1 AND index2=2 OR index1=3 AND index3=3;

下面的WHERE子句不使用索引:

 

    /* index_part1 is not used */

... WHERE index_part2=1 AND index_part3=2

 

    /*  Index is not used in both parts of the WHERE clause  */

... WHERE index=1 OR A=10

 

    /* No index spans all rows  */

... WHERE index_part1=1 OR index_part2=10

有时MySQL不使用索引,即使有可用的索引。一种情形是当优化器估计到使用索引将需要MySQL访问表中的大部分行时。(在这种情况下,表扫描可能会更快些,因为需要的搜索要少)。然而,如果此类查询使用LIMIT只搜索部分行,MySQL则使用索引,因为它可以更快地找到几行并在结果中返回。

 

Hash索引还有一些其它特征:

 

·         它们只用于使用=<=>操作符的等式比较(但很快)。它们用于比较 操作符,例如发现范围值的<

 

·         优化器不能使用hash索引来加速ORDER BY操作。(该类索引不能用来按顺序搜索下一个条目)。

 

·         MySQL不能确定在两个值之间大约有多少行(这被范围优化器用来确定使用哪个索引)。如果你将一个MyISAM表改为hash-索引的MEMORY表,会影响一些查询。

 

·         只能使用整个关键字来搜索一行。(B-树索引,任何关键字的最左面的前缀可用来找到行)。