MySQL/mariadb知识点——索引
索引
索引是特殊数据结构:定义在查找时作为查找条件的字段,索引实现在存储引擎。
- 索引可以降低服务需要扫描的数据量,减少了IO次数
- 索引可以帮助服务器避免排序和使用临时表
- 索引可以帮助将随机I/O转为顺序I/O
- 但是占用额外空间,影响插入速度
索引类型
B + Tree 索引:顺序存储,每一个叶子节点到根的距离都是相同的,左前缀索引,适合查询范围类的数据;
- 适合使用B-Tree索引的查询类型
- - 全值匹配
- - 匹配最左前缀
- - 匹配范围值
- - 精确匹配某一列并范围匹配另一列(复合索引)
- - 只访问索引的查询
- 不适合使用B-tree索引的查询类型
- - 不从最左列开始
- - 不能跳过索引中的列
- - 如果查询中某个列是为范围查询那么右侧的列无法再使用索引优化查询
Hash索引:基于哈希表,构建出键值对的索引,特别适用于精确匹配索引中的索引列,只支持等值比较查询(IN,=,<>);不适合于顺序查询,不支持模糊匹配;只有Memory存储引擎支持显式Hash索引
空间索引(R - Tree):只有MyISAM支持空间索引
全文索引(FULL TEXT):在文本中查找关键词
高性能索引策略:
- 独立使用列,尽量避免其参与运算
- 使用左前缀索引:索引构建于字段的左侧的多少字符要通过索引选择性来评估;索引选择性:不重复的索引值和数据表的记录总数的比值
- 多列索引:AND操作时更适合使用多列索引,而非为每个列创建单独的索引
- 选择合适的索引列次序:无排序和分组时,将选择性最高放左侧
索引的优化建议
- 只要列中含有NULL值,就最好不要在此例设置索引,复合索引如果有NULL值,此列在使用时也不会使用索引
- 尽量使用短索引,如果可以,应该制定一个前缀长度
- 对于经常在where子句使用的列,最好设置索引
- 对于有多个列where或者order by子句,应该建立复合索引
- 对于like语句,以%或者‘-’开头的不会使用索引,以%结尾会使用索引
- 尽量不要在列上进行运算(函数操作和表达式操作)
- 尽量不要使用not in和<>操作
- 多表连接时,尽量小表驱动大表,即小表 join 大表
- 在千万级分页时使用limit
- 对于经常使用的查询,可以开启缓存
- 大部分情况连接效率远大于子查询
管理索引
创建索引
CREATE INDEX index_name ON tbl_name (index_col_name,...);
MariaDB [hellodb]> CREATE INDEX index_name ON students(name); #创建简单索引 MariaDB [hellodb]> CREATE INDEX index_name_age ON students(name,age); #创建复合索引
示例
添加一个索引/创建一个存粹的索引
MariaDB [testdb]> alter table testtb add index ind_name(name);
创建一个联合索引
MariaDB [testdb]> create index ind_id_name on testtb1 (id,name); MariaDB [testdb]> create index ind_id_name on testtb1 (id,name(20));
查看索引
SHOW INDEXES FROM [db_name.]tbl_name;
MariaDB [hellodb]> SHOW INDEX FROM students\G
删除索引
DROP INDEX index_name ON tbl_name;
MariaDB [hellodb]> DROP INDEX index_name ON students;
重建索引 ***(mariadb中的innodb存储引擎不支持重建索引)
MariaDB [testdb]> repair table table_name quick;
优化表空间
MariaDB [hellodb]> OPTIMIZE TABLE students;
查看索引使用的情况
启用记录索引使用情况:
SET GLOBAL userstat=1;
查看索引使用情况:
SHOW INDEX_STATISTICS;
我们可以统计不经常使用的索引从而进行优化
EXPLAIN命令
通过EXPLAIN来分析索引的有效性:EXPLAIN SELECT clause
,获取查询执行计划信息,用来查看查询优化器如何执行查询
MariaDB [hellodb]> EXPLAIN SELECT name FROM students WHERE name = 'Lin Daiyu'\G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: students type: ref possible_keys: index_name_age key: index_name_age key_len: 152 ref: const rows: 1 Extra: Using where; Using index
id:当前查询语句中,每个SELECT语句的编号;复杂类型的查询有三种:简单子查询、用于FROM子句中的子查询、联合查询(UNION,注意:UNION查询的分析结果会出现一个额外匿名临时表)
select_type:
- SIMPLE :简单查询
- SUBQUERY: 简单子查询
- PRIMARY:最外面的SELECT
- DERIVED: 用于FROM中的子查询
- UNION:UNION语句的第一个之后的SELECT语句
- UNION RESULT: 匿名临时表
table:SELECT语句关联到的表
type:关联类型或访问类型,即MySQL决定的如何去查询表中的行的方式,以下顺序,性能从低到高
- ALL: 全表扫描
- index:根据索引的次序进行全表扫描;如果在Extra列出现“Using index”表示了使用覆盖索引,而非全表扫描
- range:有范围限制的根据索引实现范围扫描;扫描位置始于索引中的某一点,结束于另一点
- ref: 根据索引返回表中匹配某单个值的所有行
- eq_ref:仅返回一个行,但与需要额外与某个参考值做比较
- const, system: 直接返回单个行
possible_keys:查询可能会用到的索引
key: 查询中使用到的索引
key_len: 在索引使用的字节数
ref: 在利用key字段所表示的索引完成查询时所用的列或某常量值
rows:MySQL估计为找所有的目标行而需要读取的行数
Extra:额外信息
- Using index:MySQL将会使用覆盖索引,以避免访问表
- Using where:MySQL服务器将在存储引擎检索后,再进行一次过滤
- Using temporary:MySQL对结果排序时会使用临时表
- Using filesort:对结果使用一个外部索引排序