it技术指南:www.itedus.com
  • 信息订阅

IT指南

  • TNT五分钟问卷赢IPOD
  • 贝塔斯曼
  • 广告联盟
  • No pay, More gain!
  • 单价15元-网络广告平台
  • 注册阿里妈妈赚广告费
  • 首页
  • 新闻资讯
  • 网页制作
  • 软件使用
  • 操作系统
  • 软件编程
  • 网络编程
  • 图象处理
  • 网站欣赏
  • 数据库
  • 认证考试
  • 站长知识
正在浏览栏目导航:首页 > 数据库 > mysql >

MySQL手册版本 5.0.20-MySQL优化(三)

时间:2007-11-14 17:20:27   来源:it技术网  作者:it技术网

7.2.2 估算查询性能

在大多数情况下,可以通过统计磁盘搜索次数来估算查询的性能。对小表来说,通常情况下只需要搜索一次磁盘就能找到对应的记录(因为索引可能已经缓存起来了)。对大表来说,大致可以这么估算,它使用B树做索引,想要找到一条记录大概需要搜索的次数为:log(row_count) / log(index_block_length / 3 * 2 / (index_length + data_pointer_length)) + 1。

在MySQL中,一个索引块通常是1024bytes,数据指针通常是4bytes。对于一个有500,000条记录、索引长度为3bytes(medium integer)的表来说,根据上面的公式计算得到需要做 log(500,000)/log(1024/3*2/(3+4)) + 1 = 4 次搜索。

这个表的索引大概需要 500,000 * 7 * 3/2 = 5.2MB的存储空间(假定典型的索引缓冲区的2/3),因此应该会有更多的索引在内存中,并且可能只需要1到2次调用就能找到对应的记录。

对于写来说,大概需要4次(甚至更多)搜索才能找到新的索引位置,更新记录时通常需要2次搜索。

请注意,前面的讨论中并没有提到应用程序的性能会因为log N的值越大而下降。只要所有的东西都能由操作系统或者SQL服务器缓存起来,那么性能只会因为数据表越大而稍微下降。当数据越来越大之后,就不能全部放到缓存中去了,就会越来越慢了,除非应用程序是被磁盘搜索约束的(它跟随着的log N值增加而增加)。为了避免这种情况,可以在数据量增大以后也随着增大索引缓存容量。对 MyISAM 类型表来说,索引缓存容量是由系统变量 key_buffer_size 控制的。详情请看"7.5.2 Tuning Server Parameters"。

7.2.3 SELECT 查询的速度

通常情况下,想要让一个比较慢的 SELECT ... WHERE 查询变得更快的第一件事就是,先检查看看是否可以增加索引。所有对不同表的访问都通常使用索引。可以使用 EXPLAIN 语句来判断 SELECT 使用了哪些索引。详情请看"7.4.5 How MySQL Uses Indexes"和"7.2.1 EXPLAIN Syntax (Get Information About a SELECT)"。

以下是几个常用的提高 MyISAM 表查询速度的忠告:

想要让MySQL将查询优化的速度更快些,可以在数据表已经加载完全部数据后执行行 ANALYZE TABLE 或运行 myisamchk --analyze 命令。它更新了每个索引部分的值,这个值意味着相同记录的平均值(对于唯一索引来说,这个值则一直都是 1)。MySQL就会在当你使用基于一个非恒量表达式的两表连接时,根据这个值来决定使用哪个索引。想要查看结果,可以在分析完数据表后运行 SHOW INDEX FROM tbl_name 查看 Cardinality 字段的值。myisamchk --description --verbose 显示了索引的分布信息。

想要根据一个索引来排序数据,可以运行 myisamchk --sort-index --sort-records=1 (如果想要在索引 1 上做排序)。这对于有一个唯一索引并且想根据这个索引的顺序依次读取记录的话来说是一个提高查询速度的好办法。不过要注意的是,第一次在一个大表上做排序的话将会耗费很长时间。

7.2.4 MySQL如何优化 WHERE 子句

这个章节讲述了优化程序如何处理 WHERE 子句。例子中使用了 SELECT 语句,但是在 DELETE 和 UPDATE 语句中对 WHERE 子句的优化是一样的。

注意,关于MySQL优化的工作还在继续,因此本章节还没结束。MySQL做了很多优化工作,而不仅仅是文档中提到的这些。

MySQL的一些优化做法如下:

去除不必要的括号:

((a AND b) AND c OR (((a AND b) AND (c AND d))))

-> (a AND b AND c) OR (a AND b AND c AND d)

展开常量:

(a-> b>5 AND b=c AND a=5

去除常量条件(在展开常量时需要):

(B>=5 AND B=5) OR (B=6 AND 5=5) OR (B=7 AND 5=6)

-> B=5 OR B=6

常量表达示在索引中只计算一次

在单独一个表上做 COUNT(*) 而不使用 WHERE 时, 对于 MyISAM 和 HEAP 表就会直接从表信息中检索结果。在单独一个表上做任何表 NOT NULL 达式查询时也是这样做。  

预先探测无效的常量表达式。MySQL会快速探测一些不可能的 SELECT 语句并且不返回任何记录。

当没用 GROUP BY 或分组函数时,HAVING 和 WHERE 合并(COUNT(), MIN() 等也是如此)。

为表连接中的每个表构造一个简洁的 WHERE 语句,以得到更快的 WHERE 计算值并且尽快跳过记录。

查询中所有的常量表都会比其他表更早读取。一个常量表符合以下几个条件:

空表或者只有一条记录。

与在一个 UNIQUE 索引、或一个 PRIMARY KEY 的 WHERE 子句一起使用的表,这里所有的索引部分和常数表达式做比较并且索引部分被定义为 NOT NULL。

以下的几个表都会被当成常量表:

SELECT * FROM t WHERE primary_key=1;

SELECT * FROM t1,t2

WHERE t1.primary_key=1 AND t2.primary_key=t1.id;

MySQL会进各种可能找到表连接最好的连接方法。 如果在 ORDER BY 和 GROUP BY 子句中的所有字段都来自同一个表的话,那么在连接时这个表就会优先处理。

如果有 ORDER BY 子句和一个不同的 GROUP BY 子句,或者如果 ORDER BY 或 GROUP BY 中的字段都来自其他的表而非连接顺序中的第一个表的话,就会创建一个临时表了。

如果使用 SQL_SMALL_RESULT,MySQL就会使用内存临时表了。

所有的表索引都会查询,最好的情况就是所有的索引都会被用到,除非优化程序认为全表扫描的效率更高。同时,数据表扫描是基于判断最好的索引范围超过数据表的30%。 现在,优化程序复杂多了,它基于对一些附加因素的估计,例如表大小,记录总数,I/O块大小,因此就不能根据一个固定的百分比来决定是选择使用索引还是直接扫描数据表。

在某些情况下,MySQL可以直接从索引中取得记录而无需查询数据文件。如果所有在索引中使用的字段都是数字类型的话,只需要用索引树就能完成查询。

每条记录输出之前,那些没有匹配 HAVING 子句的就会被跳过。

以下几个查询速度非常快:

SELECT COUNT(*) FROM tbl_name;

SELECT MIN(key_part1),MAX(key_part1) FROM tbl_name;

SELECT MAX(key_part2) FROM tbl_name

WHERE key_part1=constant;

SELECT ... FROM tbl_name

ORDER BY key_part1,key_part2,... LIMIT 10;

SELECT ... FROM tbl_name

ORDER BY key_part1 DESC, key_part2 DESC, ... LIMIT 10;

以下几个查询都是使用索引树,假使那些索引字段都是数字型:

SELECT key_part1,key_part2 FROM tbl_name WHERE key_part1=val;

SELECT COUNT(*) FROM tbl_name

WHERE key_part1=val1 AND key_part2=val2;

SELECT key_part2 FROM tbl_name GROUP BY key_part1;

以下几个查询使用索引来取得经过顺序排序后的记录而无需经过独立的排序步骤:

SELECT ... FROM tbl_name

ORDER BY key_part1,key_part2,... ;

SELECT ... FROM tbl_nameORDER BY key_part1 DESC, key_part2 DESC, ... ;

7.2.5 MySQL 如何优化 OR 子句

Index Merge 方法用于使用 ref, ref_or_null, 或 range 扫描取得的记录合并起来放到一起作为结果。这种方法在表条件是或条件 ref, ref_or_null, 或 range ,并且这些条件可以用不同的键时采用。

"join"类型的优化是从 MySQL 5.0.0 开始才有的,代表者在索引的性能上有着标志性的改进,因为使用老规则的话,数据库最多只能对每个引用表使用一个索引。

在 EXPLAIN 的结果中,这种方法在 type 字段中表现为 index_merge。这种情况下,key 字段包含了所有使用的索引列表,并且 key_len 字段包含了使用的索引的最长索引部分列表。

例如:

SELECT * FROM tbl_name WHERE key_part1 = 10 OR key_part2 = 20;

SELECT * FROM tbl_name

WHERE (key_part1 = 10 OR key_part2 = 20) AND non_key_part=30;

SELECT * FROM t1,t2

WHERE (t1.key1 IN (1,2) OR t1.key2 LIKE 'value%')

AND t2.key1=t1.some_col;

SELECT * FROM t1,t2

WHERE t1.key1=1

AND (t2.key1=t1.some_col OR t2.key2=t1.some_col2);

7.2.6 MySQL 如何优化 IS NULL

MySQL在 col_name IS NULL 时做和 col_name = constant_value 一样的优化。例如,MySQL使用索引或者范围来根据 IS NUL L搜索 NULL。

SELECT * FROM tbl_name WHERE key_col IS NULL;

SELECT * FROM tbl_name WHERE key_col <=> NULL;

SELECT * FROM tbl_name

WHERE key_col=const1 OR key_col=const2 OR key_col IS NULL;

如果一个 WHERE 子句包括了一个 col_name IS NULL 条件,并且这个字段声明为 NOT NULL,那么这个表达式就会被优化。当字段可能无论如何都会产生 NULL 值时,就不会再做优化了;例如,当它来自一个 LEFT JOIN 中右边的一个表时。

MySQL 4.1.1或更高会对连接 col_name = expr AND col_name IS NULL 做额外的优化, 常见的就是子查询。EXPLAIN 当优化起作用时会显示 ref_or_null。

优化程序会为任何索引部分处理 IS NULL。

以下几个例子中都做优化了,假使字段 a 和 表 t2 中 b 有索引了:

SELECT * FROM t1 WHERE t1.a=expr OR t1.a IS NULL;

SELECT * FROM t1,t2 WHERE t1.a=t2.a OR t2.a IS NULL;

[1] [2] 下一页

关键字:MySQ
关闭此页
上一篇:MySQL手册版本 5.0.20-MySQL同步(四)
下一篇:MySQL手册版本 5.0.20-MySQL优化(二)

相关文章

     ·MySQL手册版本 5.0.20-MySQL同步(五)  (2007-11-14 17:20:31)
     ·MySQL手册版本 5.0.20-MySQL同步(四)  (2007-11-14 17:20:31)
     ·Windows 2000/XP/2003 下 IIS+PHP+MySQL+Zend Optimizer+GD库+phpMyAdmin安装配置_PHP教程  (2007-11-14 15:24:10)
     ·配置整合Win+Apache+PHP+MySQL+Tcomcat(或Resin)完全手册_PHP教程  (2007-11-14 15:24:10)
     ·详细介绍:Apache+PHP+MySQL配置攻略_PHP教程  (2007-11-14 15:24:05)
     ·windows 2000/xp/2003下安裝apache2.2.3 mysql 5.0.22 php 5.2.0_PHP教程  (2007-11-14 15:23:56)
     ·JSP连接mysql数据库攻略  (2007-11-13 12:19:51)
     ·如何才能让MySQL与OpenOffice共舞  (2007-09-09 22:40:52)
     ·Ubuntu Linux:MySQL安装指南  (2007-09-09 22:40:31)
     ·Ubuntu6.0.6下的apache2+php5+mysql配置的一些问题  (2007-09-09 22:40:27)
本栏目推荐

排行榜

  • 1Tomcat 5.5.x + mysql 5.0.x 配置连接
  • 2浅谈怎样在MySQL中直接储存图片
  • 3如何学习MySQL数据库 初学者使用指南
  • 4MySQL手册版本 5.0.20-MySQL同步(一)
  • 5MySQL手册版本 5.0.20-MySQL同步(二)
  • 6MySQL手册版本 5.0.20-MySQL同步(三)
  • 7MySQL手册版本 5.0.20-MySQL优化(一)
  • 8MySQL手册版本 5.0.20-MySQL优化(二)

最新信息

  • Tomcat 5.5.x + mysql 5.0.x 配置连接池
  • MySQL手册版本 5.0.20-MySQL同步(四)
  • MySQL手册版本 5.0.20-MySQL同步(五)
  • MySQL手册版本 5.0.20-MySQL优化(二)
  • MySQL手册版本 5.0.20-MySQL优化(三)
  • MySQL手册版本 5.0.20-MySQL同步(三)
  • MySQL手册版本 5.0.20-MySQL优化(一)
  • MySQL手册版本 5.0.20-MySQL同步(一)
关于站点 - 广告服务 - 联系我们 - 返回顶部
Copyright © 2007 www.itedus.com . All rights reserved.QQ群:8814225
如果碰到相关技术问题可以联系我们,原创相关问题请与站长及时联系.鄂ICP备07005792号