MySQL查询优化程式

2008-02-23 07:43:34来源:互联网 阅读 ()

新老客户大回馈,云服务器低至5折

在发布一个选择行的查询时, MySQL进行分析,看是否能够对他进行优化,使他执行更快。本文我们将研究查询优化程式怎样工作。更周详的信息,可参阅MySQL参考指南中的“Getting Maximum Performance from MySQL”,本文描述了MySQL采用的各种优化措施。(http://www.mysql.com/ 处的MySQL联机参考指南在不断地更新。)

MySQL查询优化程式利用了索引。当然,他也利用了其他信息。例如,假如发布下列查询,MySQL将很快地执行他,不管相应的表有多大:

SELECT * FROM tb1_name WHERE 1= 0

在此情形中,MySQL考察WHERE 子句,假如认识到不可能有满足该查询的行,就不会对该表进行搜索。可利用EXPLAIN 语句知道这一点,EXPLAIN 语句需要MySQL显示某些有关他应该执行一条SELECT 查询,而实际没有执行的信息。为了使用E X P L A I N,只需要SELECT 语句前放置EXPLAIN 即可,如下所示:

EXPLAIN SELECT * FROM tb1_name WHERE 1= 0

通常,EXPLAIN 返回的信息比这个多,包括将用来扫描表的索引、将要使用的连接类型连同需要在每个表中扫描的行数估计等等。

1 优化程式怎样工作

MySQL查询优化程式有几个目标,但其主要目标是尽量利用索引,而且尽量使用最具备限制性的索引以排除尽可能多的行。这样做可能会适得其反,因为发布一条SELECT 语句的目的是寻找行,而不是拒绝他们。优化程式这样工作的原因是从要考虑的行中排除行越快,那么找到确实符合给出标准的行就越快。假如能够首先进行最具限制性的测试,则查询能够进行得更快。假如有一个测试两列的查询,每列上都有一个索引:

WHERE coll = "some value" AND col2 = "some other value"

还假定,和col1上的测试相符的有900 行,和col2 上的测试相符的有300 行,而两个测试都通过的有30 行。假如首先测试c o l 1,必须检查900 行以找到也和col2 值相符的30 行。那么测试中有870 将失败。假如首先测试c o l 2,要找到也和col1值相符的30 行,只需检查300 行。测试中有失败270 次,这样所涉及的计算较少,磁盘I/O 也较少。遵循下列准则,有助于优化程式利用索引:

1 比较具备相同类型的列。在比较中利用索引列时,应该使用那些类型相同的列。例如,CHAR(10) 被视为和CHAR(10) 或VARCHAR(10) 相同,但不同于CHAR(12) 和VARCHAR( 12 )。INT 和BIGINT 不同。在MySQL3.23 版以前,需要使用相同类型的列,否则列上的索引将不起作用。自3.23 版后,不严格需要这样做,但相同的列类型比不同类型提供更好的性能。假如所比较的两列类型不同,可使用ALTER TABLE语句修改其中之一使他们的类型相配。

2 比较中应尽量使索引列单独。假如在函数调用或算术表达式中使用一个列,则MySQL不能使用这样的索引,因为他必须对每行计算表达式的值。有时,这是不可避免的,但很多时候,能够重新编写只取索引列本身的查询。下面的WHERE 子句说明了怎样进行这项工作。第一行中,优化程式将简化表达式4/2 为值2,然后使用my_col 上的索引快速地找到小于2 的值。而在第二个表达式中,MySQL必须检索出每行的my_col 值,乘以2,然后将结果和4 比较。没索引可用,因为列中的每个值都要检索,以便能对左边的表达式求值:

WHERE my_col < 4/2

WHERE my_col * 2 < 4

让我们考虑另一个例子。假如有一个索引列date _ c o l。假如发布如下的查询,相应的索引未被使用:

SELECT * FROM my_tb1WHERE YEAR(date_col) < 1990

其中表达式并不将索引列和1990 比较,而是将从列值计算出的值用于比较,而且必须计算每行的这个值。结果是, date_col 上的索引不可能得到使用。怎样解决?使用一个文字日期即可,这时将会使用date_col 上的索引:

WHERE date_col < "1990-01-01"

但是假如没有特定的日期值,那么可能会对找到具备出现在距今一定天数内的日期的记录感兴趣。有几种方法来编写这样的查询,但并非任何方法都很好。三种可能的方法如下:



其中第一行不能利用索引, 因为必须为每行检索列, 以便能够计算TO _ DAYS(date_col) 的值。第二行要好一些。c ut o ff 和TO _ DAY S ( CURRENT _ DATE) 两者都是常量,因此比较表达式的右边可在查询处理前由优化程式一次计算出来,而不是每行计算一次。但date_col 列仍然出现在一个函数调用中,因此,没有使用索引。第三行是最好的方法。比较表达式的右边可在执行查询前作为常量一次计算出来,但现在其值是个日期。这个值可直接和date_col 的值进行比较,不再需要转换为天数,能够利用索引。

■ 在LIKE 模式的起始处不要使用通配符。有时,有的人会用下列形式的WHERE 子句来搜索串:

WHERE col_name LIKE "%string%"

假如希望找到s t r i n g,不管他出现在列中任何位置,那么这样做是对的。但不要出于习惯在串的两边加“ %”。假如实际要查找的只是出现在列的开始处的串,则不应该要第一个“%”号。例如,假如在一个包含姓的列中查找“ M a c”起始的姓,应该编写如下的WHERE 子句:

WHERE last_name LIKE "Mac%"

优化程式考虑模式中的开始的文字部分,然后利用索引找到相符合的行。但是宁可写成如下的表达式,他允许使用last_name 上的索引:

WHERE last_name >= "Mac" AND last_name < "Mad"

这种优化对使用REGEXP 操作符的模式匹配不起作用。

■ 帮助优化程式更好地评估索引的有效性。缺省时,假如将索引列中的值和常量进行比较,优化程式将假定键字是均匀地分布在索引中的。优化程式还将对索引进行一个快速的检查,以估计在确定相应的索引是否应该用于常量的比较时要使用多少条目。可利用myisamchk 或isamchk 的--analyze 选项给优化程式提供更好的信息,以便分析键值的分布。myisamchk 用于MyISAM 表,isamchk 用于ISAM 表。为了完成键值分析,必须能够登录到MySQL服务器主机中,而且必须对表文档具备写访问权限。

标签:

版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有

上一篇: MYSQL调度和锁定问题

下一篇: MySQL索引分析和优化