Posted by Money Talks on 2012/02/23 |

第一篇 序章
第二篇 连接优化
第三篇 索引优化
第四篇 查询优化
第五篇 到实战中去

索引优化

索引优化涉及到几个方面,包括了索引的类型、如何让查询使用索引,查询是索引算法的选择等等操作。(原文链接http://ddbiz.com/?p=961)
涉及到数据库的查询时,大多数情况都是要建立索引的,MySQL的索引类型以及创建索引方式,可以参考其文档或者这里

  1. 服务器参数设置

    在于索引有关系的数据库参数中,有一些特别重要,如下:

    1. key_buffer_size

      命令行参数: –key_buffer_size=#
      ini/cnf参数: key_buffer_size
      mysql 变量: key_buffer_size
      全局变量,可动态调整,取值范围 8到4G(32bitOS), 在64bitOS上可以设置更高,只要你的系统有那么多物理内存。

      key_buffer_size 主要作用于MyISAM表的索引。我们知道,MyISAM的索引句柄是对全部连接用户共享的。状态参数 key_read_requests(响应用户请求时从缓存中获取的数据)和key_reads(响应用户请求时从文件中加载的数据) 可以用来检测key_buffer_size是否太小,根据文档, key_reads/key_read_request 应该远小于0.01(当然我们的测试环境可能完全无法达到此设定,只能尽量接近了). 如果一个MyISAM的数据表的索引文件过G,除非物理内存远远高于索引大小,否则让key_reads/key_read_request接近0.01也是一件不可能的任务。

      MySQL还支持把索引提前加载到内存,本节后面将描述此方法及其限制.

      受如下参数影响: 系统内存
      将影响如下参数: 无
      调整触发条件: key_reads/key_read_request >0.01

    2. key_cache_block_size

      与key_buffer_size相关联的另外一个参数是 key_cache_block_size
      命令行参数: –key_cache_block_size=#
      ini/cnf参数: key_cache_block_size
      mysql 变量: key_cache_block_size
      全局变量,可动态调整,取值范围 512bytes到16k。

      key_cache_block_size表明key_buffer_size被分割的区域的大小。可以通过 show status 来判断当前key_buffer_size被分为多少个块:

      Key_blocks_unused, 目前剩余可用的索引缓存空间
      Key_blocks_used(历史上的最大峰值)

      对于一个key_buffer_size=4G的数据库来说, key_cache_block_size*Key_blocks_unused 就是剩余的可用的缓存空间。只要这个空间允许,我们都应该尽可能的把索引预装入缓存中(见LOAD INDEX INTO CACHE

      理论上讲,key_cache_block_size与操作系统的I/O buffer相同大小时工作(读取、写入)效率最高,比如linux中i/o缓存一般为1k. 对于mysql来说,可以通过 –myisam-block-size来定义MyISAM索引文件的块大小,其最小为1k。

    3. key_cache_division_limit

      命令行参数: –key_cache_division_limit=1~100
      配置文件参数: key_cache_division_limit=#
      MySQL变量: key_cache_division_limit
      全局可调整变量,默认为100(即LRU队列)。
      当MyISAM的key_buffer_size中设置了key_cache_division_limit(

    4. key_cache_age_threshold

      命令行参数: –key_cache_age_threshold=100~4G(32bitOS)或者100~~(64bitOS)
      配置文件参数: key_cache_age_threshold=#
      MySQL变量: key_cache_age_threshold
      全局可调整变量,默认为300。
      当MyISAM的key_buffer_size被分为热链和温链时,key_cache_age_threshold就被用来控制什么样的情况下处于热链的数据会被转移到温链中。key_cache_age_threshold是指的block个数,如果在最近的 (key_cache_age_threshold * key_cache_division_limit/100)次访问中,处于热链顶部的block没有被访问到,那么这些块将被移到温链的顶部(处于温链顶部的block会很快被移除出key cache)。

      说明:
      key_buffer_size, key_cache_block_size, key_cache_division_limit, key_cache_age_threshold 这4个变量是一个结构变量中的一组变量。本文后续有部分详细介绍.

    5. read_buffer_size

      命令行参数: –read_buffer_size=#
      ini/cnf参数: read_buffer_size
      mysql 变量: read_buffer_size
      全局变量,可动态调整,默认128k,取值范围8k到2G.

      read_buffer_size主要作用于顺序读取一批数据时,减少数据库文件访问的次数。

      受如下参数影响:
      将影响如下参数: KEY_BLOCK_SIZE(表创建时的参数)
      调整触发条件:

    6. read_rnd_buffer_size

      命令行参数: –read_rnd_buffer_size=#
      ini/cnf参数: read_rnd_buffer_size
      mysql 变量: read_rnd_buffer_size
      全局变量,可动态调整,默认256k,取值范围8k到4G.

      read_rnd_buffer_size用于使用键/索引进行排序时的磁盘文件预读,一个足够大的read_rnd_buffer_size对ORDER BY语句会有很大影响。
      注意:read_rnd_buffer_size是和每一个session相关的,因此其大小需要谨慎处理,当并发连接很大时,尤其要小心。

  2. LOAD CACHE INTO CACHE

    MySQL可以把索引文件预先加载到指定的缓存中:

    LOAD INDEX INTO CACHE table_name;
    LOAD INDEX INTO CACHE table_name INDEX (index_name_1, index_name_2);
    LOAD INDEX INTO CACHE table_name INDEX (index_name_1, index_name_2) IGNORE LEAVES;

    对于查询型的超大型的表,当没有足够的内存时,可以使用 IGNORE LEAVES 的方式加载索引到缓存。比如一个接近1Billion的数据表,其索引可能也是几G大小的。下面这个例子就显示了当预先加载数据索引时,查询的速度变化,这个数据表有接近1亿条记录,3个索引,有超过3G的大小,对于同一个查询:

    #mysql> select * from tbigdatatable where username in (‘ABCDEF’, ‘19740821’)

    在非预先加载索引以及预载索引的情况下,查询的响应区别:

    #mysqld_safe –key-buffer-cache=1073741824
    ####不预载索引#### 5 rows in set (0.65 sec)
    ######预载索引#### 5 rows in set (1.94 sec)

    当然一个查询有很大的偶然性,不过从一个大量的查询平均来看,这个效果还是有很大的差别的。

    如果一个表的索引包含不同的key_block_size,那么这个预装载将会遇到困难, 如:

    alter table tbigdatatable add index idx_bigdatatable_username(username) key_block_size=8192, add index idx_bigdatatable_email(email) key_block_size=8192, add index idx_bigdatatable_id(id) key_block_size=1024;
    load index into cache tbigdatatable index (idx_bigdatatable_username, idx_bigdatatable_email) ignore leaves;
    +————————+————–+———-+————————————-+
    | Table | Op | Msg_type | Msg_text |
    +————————+————–+———-+————————————-+
    | coredata.tbigdatatable | preload_keys | error | Indexes use different block sizes |
    | coredata.tbigdatatable | preload_keys | error | Subpartition p178sp0 returned error |
    | coredata.tbigdatatable | preload_keys | status | Operation failed |
    +————————+————–+———-+————————————-+

    因为.MYI中包含不同block_size的索引,所以无法预加载!

    MySQL 5.1 对分区表不能预装载索引:
    preload_keys | note | The storage engine for the table doesn’t support preload_keys
    真是不幸, 这些版本包括: 5.1.47, 5.1.61-community-log

    因为手头上没有MySQL5.5的数据库可供使用,所以关于预装载索引到内存的方法只能暂时放一放,这也导致了我的另外一个测试项目差点夭折:9千万数据的分区表查询,每个查询要耗时1m左右,伤不起啊。

  3. CACHE INDEX

    LOAD INDEX INTO CACHE可以把索引装入缓存中,除此外,MySQL还可以更有针对性的把索引装入制定的缓存中。key_buffer_size是一个结构中一个变量,这个结构是系统的默认缓存空间,我们还可以设定其他的缓存空间,比如:

    set global key1.key_buffer_size=128*1024*1024;
    set global key2.key_buffer_size=512*1024*1024;

    这样我们就能定义不同的缓存空间,配合 CACHE INDEX IN cache_region语句,就可以把不同的索引放入不同的缓存中。

    (接上)
    cache index table_name index (index_name_1) in key1;
    cache index table_name index (index_name_2) in key2;
    load cache into cache table_name index (index_name_1);
    load cache into cache table_name index (index_name_2) ignore leaves;

    上面的语句就把 index_name_1放入了 key1, 把 index_name_2放入了 key2;至于何时使用不同的缓存,我们在后面的实战中再做讨论。

    结构化的变量,在mysql中没办法用 show variables like ‘structure_name_1.key_buffer%’ ; 的方式来查询。假如我们定义了不同的结构变量(创建不同的缓存空间的): staticdb.*,则可以用下面的方式来查询该空间的设置情况:

    set global staticdb.key_buffer_size=1000*1024*1024;
    —————————————————
    mysql> select @@global.staticdb.key_buffer_size KBS
    , @@global.staticdb.key_cache_division_limit KCDL
    , @@global.staticdb.key_cache_age_threshold KCAT
    , @@global.staticdb.key_cache_block_size KCBS;
    +————+——+——+——+
    | KBS | KCDL | KCAT | KCBS |
    +————+——+——+——+
    | 1048576000 | 100 | 300 | 1024 |
    +————+——+——+——+
    1 row in set (0.00 sec)

    目前我还没有办法查看指定一个结构空间的使用情况,如果你知道如何查看的话,请留言给我。

  4. 要点总结

    本节的要点是:

    对于MyISAM来说:设置尽可能大的缓存,最好把MyISAM表的索引能够全部装入缓存中

mysql优化之索引优化的更多相关文章

  1. MySQL 数据库性能优化之索引优化

    接着上一篇 MySQL 数据库性能优化之表结构,这是 MySQL数据库性能优化专题 系列的第三篇文章:MySQL 数据库性能优化之索引优化 大家都知道索引对于数据访问的性能有非常关键的作用,都知道索引 ...

  2. MySQL中的索引优化

    MySQL中的SQL的常见优化策略 MySQL中的索引优化 MySQL中的索引简介 过多的使用索引将会造成滥用.因此索引也会有它的缺点.虽然索引大大提高了查询速度,同时却会降低更新表的速度,如对表进行 ...

  3. MySql在建立索引优化时需要注意的问题

    MySql在建立索引优化时需要注意的问题 设计好MySql的索引可以让你的数据库飞起来,大大的提高数据库效率.设计MySql索引的时候有一下几点注意: 1,创建索引 对于查询占主要的应用来说,索引显得 ...

  4. SQL通用优化方案(where优化、索引优化、分页优化、事务优化、临时表优化)

    SQL通用优化方案:1. 使用参数化查询:防止SQL注入,预编译SQL命令提高效率2. 去掉不必要的查询和搜索字段:其实在项目的实际应用中,很多查询条件是可有可无的,能从源头上避免的多余功能尽量砍掉, ...

  5. MySQL如何利用索引优化ORDER BY排序语句

    MySQL索引通常是被用于提高WHERE条件的数据行匹配或者执行联结操作时匹配其它表的数据行的搜索速度. MySQL也能利用索引来快速地执行ORDER BY和GROUP BY语句的排序和分组操作. 通 ...

  6. MySQL如何利用索引优化ORDER BY排序语句 【转载】

    本文转载自:http://blog.csdn.net/ryb7899/article/details/5580624  .感谢相关作者. MySQL索引通常是被用于提高WHERE条件的数据行匹配或者执 ...

  7. MySQL优化四 索引优化

    索引为什么能提高数据访问性能? 很多人只知道索引能够提高数据库的性能,但并不是特别了解其原理,其实我们可以用一个生活中的示例来理解. 我们让一位不太懂计算机的朋友去图书馆确认一本叫做<MySQL ...

  8. MySQL 多列索引优化小记

    MySQL 5.6.30 问题背景 由于爬虫抓取的数据不断增多,这两天在不断对数据库以及查询语句进行优化,其中一个表结构如下: CREATE TABLE `newspaper_article` ( ` ...

  9. mysql性能优化之索引优化

    作为免费又高效的数据库,mysql基本是首选.良好的安全连接,自带查询解析.sql语句优化,使用读写锁(细化到行).事物隔离和多版本并发控制提高并发,完备的事务日志记录,强大的存储引擎提供高效查询(表 ...

随机推荐

  1. Eclipse使用技巧及个性化设计

    以下除特殊说明均在 Windows->Preferences里面操作 如何把Eclipse关闭提示调出来? General->Startup and Shutdown,在 Confirm ...

  2. mapreduce实现全局排序

    直接附代码,说明都在源码里了. package com.hadoop.totalsort; import java.io.IOException; import java.util.ArrayList ...

  3. Class org.apache.struts2.json.JSONWriter can not access a member of

    异常形式: Class org.apache.struts2.json.JSONWriter can not access a member of * 或是 Class com.googlecode. ...

  4. 【转】Android 4.4源码下载与编译

    原文网址:http://www.cnblogs.com/zhx831/p/3550830.html 这篇文章记录了我下载源码和编译的全过程, 全过程参考Android官方文档 1. 下载Android ...

  5. HTTP2.0那些事

    1. HTTP2.0的前世 http2.0的前世是http1.0和http1.1这两兄弟.虽然之前仅仅只有两个版本,但这两个版本所包含的协议规范之庞大,足以让任何一个有经验的工程师为之头疼.http1 ...

  6. NOIP2013 花匠 DP 线段树优化

    网上一堆题解,我写的是N^2优化的那种,nlogn,O(n)的那种能看懂,但是让我自己在赛场写,肯定没戏了 #include <cstdio> #include <iostream& ...

  7. HDU 5651 xiaoxin juju needs help 水题一发

    分析:求一下组合数 首先,如果不止一个字符出现的次数为奇数,则结果为0. 否则,我们把每个字符出现次数除2,也就是考虑一半的情况. 那么结果就是这个可重复集合的排列数了. fact(n)/fact(a ...

  8. web_reg_find()查询信息为变量

    Action(){char *str1;//=(char*)malloc(20);char str2[10]; web_url("toLoginPage", "URL={ ...

  9. [POJ3684]Physics Experiment

      Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 1363   Accepted: 476   Special Judge ...

  10. globalfifo设备驱动

    把globalmem中的全局内存变成一个FIFO,只有当FIFO中有数据的时候(即有进程把数据写到这个FIFO而且没有被读进程读空),读进程才能把数据读出,而且读取后的数据会从globalmem的全局 ...