索引(Index)是帮助 MySQL 高效获取数据的数据结构。常见的查询算法,顺序查找,二分查找,二叉排序树查找,哈希散列法,分块查找,平衡多路搜索树 B 树(B-tree)。
1. 常见索引原则有
1.1 选择唯一性索引
唯一性索引的值是唯一的,可以更快速的通过该索引来确定某条记录。
1.2 为经常需要排序、分组和联合操作的字段建立索引
1.3 为常作为查询条件的字段建立索引
1.4 限制索引的数目
越多的索引,会使更新表变得很浪费时间
1.5 尽量使用数据量少的索引
如果索引的值很长,那么查询的速度会受到影响。
1.6 尽量使用前缀来索引
如果索引字段的值很长,最好使用值的前缀来索引。
1.7 删除不再使用或者很少使用的索引
1.8 最左前缀匹配原则,非常重要的原则
1.9 尽量选择区分度高的列作为索引
区分度的公式是表示字段不重复的比
1.10 索引列不能参与计算,保持列“干净”:带函数的查询不参与索引
1.11 尽量的扩展索引,不要新建索引。
2. 索引选取类型
2.1 越小的数据类型通常更好
越小的数据类型通常在磁盘、内存和CPU缓存中都需要更少的空间,处理起来更快。
2.2 简单的数据类型更好
整型数据比起字符,处理开销更小,因为字符串的比较更复杂。
2.3 尽量避免NULL
应该指定列为NOT nuLL,在MySQL中, 含有空值的列很难进行查询优化,因为它们使得索引、索引的统计信息以及比较运算更加复杂
3. 索引优缺点
3.1 优点
索引由数据库中一列或多列组合而成,其作用是提高对表中数据的查询速度
索引的优点是可以提高检索数据的速度
3.2 缺点
索引的缺点是创建和维护索引需要耗费时间
索引可以提高查询速度,会减慢写入速度
索引并不是越多越好,索引固然可以提高相应的 select 的效率,但同时也降低了 insert 及 update 的效率,因为 insert 或 update 时有可能会重建索引,所以怎样建索引需要慎重考虑,视具体情况而定。一个表的索引数最好不要超过6个,若太多则应考虑一些不常使用到的列上建的索引是否有必要。
4. 索引分类
4.1 普通索引
仅加速查询 最基本的索引,没有任何限制,是我们大多数情况下使用到的索引。
CREATE INDEX index_name(索引名) on user_info(表名)(name) (字段名);
eg:CREATE INDEX sudId on test_person (sub_id) ;
4.2 唯一索引
与普通索引类型,不同的是:加速查询 + 列值唯一(可以有null)
CREATE UNIQUE INDEX mail on user_info(name) ;
eg: CREATE UNIQUE INDEX cardId on test_person(cardId);
4.3 全文索引
全文索引(FULLTEXT)仅可以适用于MyISAM引擎的数据表;作用于CHAR、VARCHAR、TEXT数据类型的列。
4.4 组合索引
将几个列作为一条索引进行检索,使用最左匹配原则。
eg:create INDEX tableCard on test_person(table_id,cardId);
5.索引常用操作
5.1 删除索引
方式一:
eg: drop INDEX tableCard on test_person;
方式二:
eg: alter TABLE test_person drop index tableCard;
5.2 查看索引
show index from test_person;
5.3 通过 EXPLAIN 分析低效 SQL 的执行计划
通过以上步骤查询到效率低的 SQL 语句后,可以通过 EXPLAIN 或者 DESC 命令获取 MySQL如何执行 SELECT 语句的信息,包括在 SELECT 语句执行过程中表如何连接和连接的顺序。
explain select * from test_personwhere cardId='233909023109328711';
每个列的简单解释如下:
select_type: 表示 SELECT 的类型,常见的取值有
SIMPLE(简单表,即不使用表连接或者子查询)
PRIMARY(主查询,即外层的查询)
UNION(UNION 中的第二个或者后面的查询语句)
SUBQUERY(子查询中的第一个 SELECT)等。
table: 输出结果集的表。
type: 表示表的连接类型,性能由好到差的连接类型为
system(表中仅有一行,即常量表)
const(单表中最多有一个匹配行,例如 primary key 或者 unique index)
eq_ref(对于前面的每一行,在此表中只查询一条记录,简单来说,就是多表连接中使用 primary key 或者 unique index)
ref(与 eq_ref 类似,区别在于不是使用 primary key 或者 unique index,而是使用普通的索引)
ref_or_null(与 ref 类似,区别在于条件中包含对 NULL 的查询)
index_merge(索引合并优化)
unique_subquery(in的后面是一个查询主键字段的子查询)
index_subquery (与 unique_subquery 类似,区别在于 in 的后面是查询非唯一索引字段的子查询)
range (单表中的范围查询)
index (对于前面的每一行,都通过查询索引来得到数据)
all (对于前面的每一行,都通过全表扫描来得到数据)
possible_keys: 表示查询时,可能使用的索引。
key: 表示实际使用的索引。
key_len: 索引字段的长度。
rows: 扫描行的数量。
Extra: 执行情况的说明和描述。
5.4 定期分析表和检查表
分析表的语法如下:
ANALYZE [LOCAL | NO_WRITE_TO_BINLOG] TABLE tbl_name [, tbl_name] ...
本语句用于分析和存储表的关键字分布,分析的结果将可以使得系统得到准确的统计信息,使得 SQL 能够生成正确的执行计划。如果用户感觉实际执行计划并不是预期的执行计划,执行一次分析表可能会解决问题。在分析期间,使用一个读取锁定对表进行锁定。这对于 MyISAM, BDB 和 InnoDB 表有作用。
eg:ANALYZE TABLE test_person;
5.5 检查表的语法
检查表的作用是检查一个或多个表是否有错误。 CHECK TABLE 对 MyISAM 和 InnoDB 表有作用。对于 MyISAM 表,关键字统计数据被更新,例如:
CHECK TABLE tbl_name [, tbl_name] ... [option] ... option = {QUICK | FAST | MEDIUM | EXTENDED | CHANGED}
5.6 定期优化表
如果已经删除了表的一大部分,或者如果已经对含有可变长度行的表(含有 VARCHAR、BLOB 或 TEXT 列的表)进行了很多更改,则应使用 OPTIMIZE TABLE 命令来进行表优化。这个命令可以将表中的空间碎片进行合并,并且可以消除由于删除或者更新造成的空间浪费,但OPTIMIZE TABLE 命令只对 MyISAM、BDB 和 InnoDB 表起作用。
优化表的语法如下:
OPTIMIZE [LOCAL | NO_WRITE_TO_BINLOG] TABLE tbl_name [, tbl_name] ...
注意:ANALYZE、CHECK、OPTIMIZE 执行期间将对表进行锁定,因此一定注意要在数据库不繁忙的时候执行相关的操作。
网友评论