专注于互联网--专注于架构

最新标签
网站地图
文章索引
Rss订阅

首页 »数据库 » mysql数据库优化:数据库管理进阶,MySQL索引分析和优化 »正文

mysql数据库优化:数据库管理进阶,MySQL索引分析和优化

来源: 发布时间:星期四, 2009年2月12日 浏览:45次 评论:0



  索引用来快速地寻找那些具有特定值记录所有MySQL索引都以B-树形式保存如果没有索引执行查询时MySQL必须从第个记录开始扫描整个表所有记录直至找到符合要求记录表里面记录数量越多这个操作代价就越高如果作为搜索条件列上已经创建了索引MySQL无需扫描任何记录即可迅速得到目标记录所在位置如果表有1000个记录通过索引查找记录至少要比顺序扫描记录快100倍
  
  假设我们创建了个名为people表:
  
  CREATE TABLE people ( peopleid SMALLINT NOT NULL, name CHAR(50) NOT NULL );
  
  然后我们完全随机把1000个区别name值插入到people表下图显示了people表所在数据文件小部分:
  
  可以看到在数据文件中name列没有任何明确次序如果我们创建了name列索引MySQL将在索引中排序name列:
  
  对于索引中MySQL在内部为它保存个数据文件中实际记录所在位置“指针”因此如果我们要查找name等于“Mike”记录peopleid(SQL命令为“SELECT peopleid FROM people WHERE name='Mike';”)MySQL能够在name索引中查找“Mike”值然后直接转到数据文件中相应准确地返回该行peopleid(999)在这个过程中MySQL只需处理个行就可以返回结果如果没有“name”列索引MySQL要扫描数据文件中所有记录即1000个记录!显然需要MySQL处理记录数量越少则它完成任务速度就越快
  
  索引类型
  
  MySQL提供多种索引类型供选择:
  
  普通索引
  这是最基本索引类型而且它没有唯性的类限制普通索引可以通过以下几种方式创建:
  
  创建索引例如CREATE INDEX <索引名字> _disibledevent=>  
  首先我们可以考虑在单个列上创建索引比如firstname、lastname或者age列如果我们创建firstname列索引(ALTER TABLE people ADD INDEX firstname (firstname);)MySQL将通过这个索引迅速把搜索范围限制到那些firstname='Mike'记录然后再在这个“中间结果集”上进行其他条件搜索:它首先排除那些lastname不等于“Sullivan”记录然后排除那些age不等于17记录当记录满足所有搜索条件的后MySQL就返回最终搜索结果
  
  由于建立了firstname列索引和执行表完全扫描相比MySQL效率提高了很多但我们要求MySQL扫描记录数量仍旧远远超过了实际所需要虽然我们可以删除firstname列上索引再创建lastname或者age列索引但总地看来不论在哪个列上创建索引搜索效率仍旧相似
  
  为了提高搜索效率我们需要考虑运用多列索引如果为firstname、lastname和age这 3个列创建个多列索引MySQL只需次检索就能够找出正确结果!下面是创建这个多列索引SQL命令:
  
  ALTER TABLE people ADD INDEX fname_lname_age (firstname,lastname,age);
  
  由于索引文件以B-树格式保存MySQL能够立即转到合适firstname然后再转到合适lastname最后转到合适age在没有扫描数据文件任何个记录情况下MySQL就正确地找出了搜索目标记录!
  
  那么如果在firstname、lastname、age这 3个列上分别创建单列索引效果是否和创建个firstname、lastname、age多列索引样呢?答案是否定两者完全区别当我们执行查询时候MySQL只能使用个索引如果你有 3个单列索引MySQL会试图选择个限制最严格索引但是即使是限制最严格单列索引限制能力也肯定远远低于firstname、lastname、age这 3个列上多列索引
  
  最左前缀
  
  多列索引还有另外个优点它通过称为最左前缀(Leftmost Prefixing)概念体现出来继续考虑前面例子现在我们有个firstname、lastname、age列上多列索引我们称这个索引为fname_lname_age当搜索条件是以下各种列组合时MySQL将使用fname_lname_age索引:
  
  firstnamelastnameage
  firstnamelastname
  firstname
  
  从另方面理解它相当于我们创建了(firstnamelastnameage)、(firstnamelastname)以及(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'; The
  following queries cannot use the index at all: SELECT peopleid FROM people WHERE
  lastname='Sullivan'; SELECT peopleid FROM people WHERE age='17'; SELECT peopleid
  FROM people WHERE lastname='Sullivan' AND age='17';
  
  选择索引列
  在性能优化过程中选择在哪些列上创建索引是最重要步骤的可以考虑使用索引主要有两种类型列:在WHERE子句中出现在join子句中出现请看下面这个查询:
  
  SELECT age ## 不使用索引 FROM people WHERE firstname='Mike' ## 考虑使用索引 AND
  lastname='Sullivan' ## 考虑使用索引
  
  这个查询和前面查询略有区别但仍属于简单查询由于age是在SELECT部分被引用MySQL不会用它来限制列选择操作因此对于这个查询来说创建age列索引没有什么必要下面是个更复杂例子:
  
  SELECT people.age, ##不使用索引 town.name ##不使用索引 FROM people LEFT JOIN town _disibledevent=>  lastname='Sullivan' ##考虑使用索引
  
  和前面例子由于firstname和lastname出现在WHERE子句中因此这两个列仍旧有创建索引必要除此的外由于town表townid列出现在join子句中因此我们需要考虑创建该列索引
  
  那么我们是否可以简单地认为应该索引WHERE子句和join子句中出现个列呢?差不多如此但并不完全我们还必须考虑到对列进行比较操作符类型MySQL只有对以下操作符才使用索引:<<==>>=BETWEENIN以及某些时候LIKE可以在LIKE操作中使用索引情形是指另个操作数不是以通配符(%或者_)开头情形例如“SELECT peopleid FROM people WHERE firstname LIKE 'Mich%';”这个查询将使用索引但“SELECT peopleid FROM people WHERE firstname LIKE '%ike';”这个查询不会使用索引
  
  分析索引效率
  现在我们已经知道了些如何选择索引列知识但还无法判断哪个最有效M
0

相关文章

读者评论

发表评论

  • 昵称:
  • 内容: