写在前面的话html
查询容易,优化不易,且写且珍惜mysql
从MySQL逻辑架构来看,MySQL有三层架构,第一层链接,第二层查询解析、分析、优化、视图、缓存,第三层,存储引擎算法
从数据结构角度sql
一、B+树索引(O(log(n))):关于B+树索引,能够参考 MySQL索引背后的数据结构及算法原理segmentfault
二、hash索引:
a 仅仅能知足"=","IN"和"<=>"查询,不能使用范围查询
b 其检索效率很是高,索引的检索能够一次定位,不像B-Tree 索引须要从根节点到枝节点,最后才能访问到页节点这样屡次的IO访问,因此 Hash 索引的查询效率要远高于 B-Tree 索引
c 只有Memory存储引擎显示支持hash索引缓存
三、FULLTEXT索引(如今MyISAM和InnoDB引擎都支持了)数据结构
四、R-Tree索引(用于对GIS数据类型建立SPATIAL索引)架构
从物理存储角度函数
一、汇集索引(clustered index)工具
二、非汇集索引(non-clustered index)
从逻辑角度
一、主键索引:主键索引是一种特殊的惟一索引,不容许有空值
二、普通索引或者单列索引
三、多列索引(复合索引):复合索引指多个字段上建立的索引,只有在查询条件中使用了建立索引时的第一个字段,索引才会被使用。使用复合索引时遵循最左前缀集合
四、惟一索引或者非惟一索引
五、空间索引:空间索引是对空间数据类型的字段创建的索引,MYSQL中的空间数据类型有4种,分别是GEOMETRY、POINT、LINESTRING、POLYGON。
MYSQL使用SPATIAL关键字进行扩展,使得可以用于建立正规索引类型的语法建立空间索引。建立空间索引的列,必须将其声明为NOT NULL,空间索引只能在存储引擎为MYISAM的表中建立
CREATE TABLE table_name[col_name data type] [unique|fulltext|spatial][index|key][index_name](col_name[length])[asc|desc] 一、unique|fulltext|spatial为可选参数,分别表示惟一索引、全文索引和空间索引; 二、index和key为同义词,二者做用相同,用来指定建立索引 三、col_name为须要建立索引的字段列,该列必须从数据表中该定义的多个列中选择; 四、index_name指定索引的名称,为可选参数,若是不指定,MYSQL默认col_name为索引值; 五、length为可选参数,表示索引的长度,只有字符串类型的字段才能指定索引长度; 六、asc或desc指定升序或降序的索引值存储
一、基数很低的字段不建立索引,更新很是频繁的字段不适合建立索引
二、MySQL不支持bitmap索引
三、采用第三方系统实现 Text/Blob 的全文索引(Sphinx、Coreseek、Lucene、ElashSearch)
四、经常使用的 where、ORDER BY 、GROUP BY 、DISTINCT 字段要创建索引
五、索引不能太多,会有负做用
六、多使用联合索引、少使用独立索引
七、字符型可建立前缀索引(如 username 字段 80% 的数据都小于18个字符,那么能够建立18个字符的前缀索引
八、字段的顺序对组合索引效率有相当重要的做用,过滤效果越好的字段须要更靠前
最左前缀匹配原则,很是重要的原则,mysql会一直向右匹配直到遇到范围查询(>、<、between、like)就中止匹配,好比a = 1 and b = 2 and c > 3 and d = 4 若是创建(a,b,c,d)顺序的索引,d是用不到索引的,若是创建(a,b,d,c)的索引则均可以用到,a,b,d的顺序能够任意调整尽可能的扩展索引,不要新建索引。好比表中已经有a的索引,如今要加(a,b)的索引,那么只须要修改原来的索引便可=和in能够乱序,好比a = 1 and b = 2 and c = 3 创建(a,b,c)索引能够任意顺序,mysql的查询优化器会帮你优化成索引能够识别的形式
九、MySQL只对如下操做符才使用索引
<,<=,=,>,>=,between
,like(不以通配符%或_开头的情形)
十、不要过分索引,只保持所需的索引。每一个额外的索引都要占用额外的磁盘空间,并下降写操做的性能。 在修改表的内容时,索引必须进行更新,有时可能须要重构,所以,索引越多,所花的时间越长。
一、经过索引扫描的记录数超过30%会进行全表扫描
二、第一个索引列使用范围查询不能使用索引
三、内存表使用Hash进行全表扫描
四、ORDER BY 、GROUP BY Hash索引只能进行等于/不等于的检索
五、SELECT … WHERE key1 = ? ORDER BY key2 ASC 对于key1和key2上的索引,查询优化器会本身判断用哪一个(只能用到一个)
六、表关联字段类型要同样(包括长度),不然会有类型转换
七、使用函数时不能用到索引( WHERE func(key1) = ? 不能用到)( WHERE key1 + 1 = ? 不能用到)(WHERE key1 = ? + ? 能够用到)
一、增,删,改都须要修订索引,索引存在额外的维护成本
二、查找翻阅索引系统须要消耗时间,索引存在额外的访问成本
三、索引系统须要一个地方来存放,索引存在额外的空间成本
mysqlidxchx/pt-index-usage/userstat/check-unused-keys
一、mysqlidxchx工具很长时间没有更新,但主要用来分析general log、slow.log,来判断实例中那个索引是能够删除,但这个工具没有通过实战,风险很大。
二、pt-index-usage原理来相似mysqlidxchx,执行过程当中性能消耗比较严重,若是要在生产库上部署,最好在凌晨业务低锋时使用,pt-index-usage只支持slow.log格式的文件,若是要全面分析整个实例索引使用状况,须要long_query_time设置成0,才能把因此的sql记录下来,但同时会对磁盘空间形成压力,同时pt-index-usage对大文件分析就是件痛苦的事。固然pt-index-usage能够考虑部分表索引使用状况的确认。
三、最看好的userstat,收集信息性能优越,成本低。这个patch是google贡献的(userstat_running),percona把它更名成userstat,默认是不开启的,开启是会收集客户端、索引、表、线程信息存储在CLIENT_STATISTICS、INDEX_STATISTICS、TABLE_STATISTICS、THREAD_STATISTICS。Userstat的bug致使的问题太严重,直接致使mysql crash,到目前淘宝生产环境尚未使用。
四、Ryan Lowe的check-unused-keys脚本基于userstat,可以比较方便输出须要删除的索引。
参考地址
http://www.mysqlperformanceblog.com/2012/06/30/find-unused-indexes/http://www.mysqlperformanceblog.com/2012/12/05/quickly-finding-unused-indexes-and-estimating-their-size/http://www.mysqlperformanceblog.com/2009/06/26/check-unused-keys-a-tool-to-interact-with-index_statistics/