MySql 如何实现的索引机制:
MySQL 中索引分三类: B+ 树索引、 Hash 索引、全文索引
InnoDB 索引 与 MyISAM 索引实现的区别是什么:
如果有主键则会根据主键创建B+树,如果没有主键则以隐式rowId来创建B+树。
B+ 树实现原理:
假设有个表 index_demo, 表中有 2个 INT类型的列,1个CHAR(1)类型的列,c1 列为主键
CREATE TABLE index_demo(c1 INT, c2 INT, c3 CHAR(1), PRIMARY KEY(c1));
index_demo 表的简化的行格式示意图如下:
InnoDB 的主键索引方案:
InnoDB 的非主键索引(c2)方案:
聚簇索引与非聚簇索引 B+ 树实现有什么区别:
聚簇索引是主键作为索引的值,有且仅能只有一个。除了聚簇索引之外创建的一切索引,都称为非聚簇索引
索引类型 | 特点 | 优点 | 缺点 | 限制 |
聚簇索引 |
|
|
|
|
非聚簇索引(c2)的不同之处:
B+ 树中可以存放多少条索引记录:
自适应哈希索引:
是 InnoDB 引擎的一个特殊功能,当它注意到某些索引值被使用的非常频繁时,会在内存种基于 BTree 所有之上再创建一个哈希索引,这就让BTree索引也具有哈希索引的一些优点。这一过程完全是内部行为,用户无法控制或配置。
SHOW ENGINE INNODB STATUS \G;
自增主键和字符串主键的区别:
自增ID,删除添加和删除重启后添加区别:
索引的优缺点:
索引类型 | 优点 | |
聚簇(主键)索引 |
|
空间上代价: 每建立一个索引都要为它建立一颗 B+ 树,每一颗 B+树的每一个节点都是一个数据页,一个页默认会占用 16KB 的存储空间,一颗很大的 B+ 树由许多数据页组成,那就是很大的一片存储空间 时间上的代价: 每次对表中数据进行 增、删、改 操作时,都需要去修改各个 B+ 树索引。并且可能对节点和记录排序造成破坏,所以存储引擎需要额外的时间进行一些记录移位、页面分裂、页面回收等操作来维护好节点和记录的排序 |
非聚簇索引 |
|
大段文本内容,如果创建(优化)索引:
CRUD 时聚簇索引与非聚簇索引的区别:
非聚簇索引为什么不存数据地址而存储主键:
因为聚簇索引有时会引发分页操作、重排操作数据有可能会移动
回表操作和覆盖索引:
比如 字段有 id age name sex, 以 age 建立索引
执行 select * from user where age > 20; 非聚簇索引需要执行找到大于 20 的主键ID,然后回表查询具体数据
select age from user where age > 20; 想要的数据在B+树中,则不需要回表操作,并且查询效率很高(尽量不查询非必要字段),即覆盖索引。
为什么要回表查询:
联合索引、组合索引、复合索引:
create index idx_c2_c3 on user (c2, c3)
为c2 和 c3 列创建联合索引,先拿 c2 进行排序,然后c3 进行排序。
全职匹配:where 条件要全职匹配索引创建的顺序,不可颠倒
最左前缀:可以拿 c2 (第一个索引) 进行查询
唯一索引:
CREATE TABLE customer(
id INT UNSIGNED AUTO_INCREMENT,
customer_no VARCHAR(200),
customer_name VARCHAR(200),
PRIMARY KEY(id), -- 主键索引:列设定为主键后会自动建立索引,唯一且不能为空
UNIQUE INDEX uk_no (customer_no), -- 唯一索引: 索引列值必须唯一,允许有NULL值,且NULL可能会出现多次。
KEY index_name(customer_name), -- 普通索引:既不是主键,列值也不需要唯一,单纯的为了提高查询速度而创建
KEY index_no_name(customer_no, customer_name) -- 复合索引: 即一个索引包含了多个列
);
CREATE TABLE customer(
id INT UNSIGNED AUTO_INCREMENT,
customer_no VARCHAR(200),
customer_name VARCHAR(200),
);
ALTER TABLE customer ADD PRIMARY KEY customer(id); -- 主键索引
CREATE UNIQUE INDEX uk_no ON customer(customer_no); -- 唯一索引
CREATE INDEX idx_name ON customer(customer_name); -- 普通索引
CREATE INDEX idx_no_name ON customer(customer_no, customer_name); -- 复合索引
唯一索引是否影响性能:
适合创建索引:
不适合创建索引:
索引下推:
是否开启索引下推 | 效果 |
未开启索引下推 |
|
开启索引下推 |
|
哪些情况会导致索引失效:
-- 显示查询分析
EXPLAIN SELECT * FROM emp WHERE emp.name LIKE 'abc%';
EXPLAIN SELECT * FROM emp WHERE LEFT(emp.name,3) = 'abc'; -- 索引失效
SELECT * FROM emp WHERE NAME LIKE '%ab%'; -- 索引失效
SELECT SQL_NO_CACHE * FROM emp WHERE emp.name <> 'abc'; -- 索引失效
SELECT * FROM emp WHERE emp.name IS NOT NULL; -- 索引失效
SELECT * FROM emp WHERE name = 123;
SELECT * FROM emp WHERE name = "abc"; -- age, name 为组合索引
为什么 LIKE 以 % 开头索引会失效:
有字段 id, name, age。 name 创建索引
seLect * from user where name like '%名'; -- type = all 索引失效
select name from user where name like '%名'; -- type = index, 覆盖索引
没有高效使用索引是因为字符串索引会逐个转换accii码, 生成 B+ 树时按首个字符串顺序排序,类似复合索引未用左列字段失效一样,跳过开头部分也就无法使用生成的 B+ 树了。
如何查看一个表的索引:
show index from t_emp;
explain select * from t_emp where id = 1; -- 显示可能会用到的索引以及最终使用的索引
能否查看索引选择逻辑,使用 optimizer_trace:
set session optimizer_trace = "enabled=on", end_markers_in_json=on; -- 转换 json 格式输出
select * from t_emp where deptid = 1; -- 执行SQL
SELECT * FROM information_schema.OPTIMIZER_TRACE; -- 优化器选择, cost 会计算每个索引所花费的情况
set session optimizer_trace = "enabled=off";
多个索引优先级是如何匹配的:
索引使用一般性建议:
使用 Order By 时能否通过索引排序:
没有过滤条件不走索引
通过索引排序内部流程:
双路排序和单路排序:
group by 分组和 order by 在索引使用上的区别:
group by 使用索引的原则几乎跟 order by 一致,唯一区别: