mysql - MySQL 中的聚集索引
问题描述
我正在学习数据库中的索引。根据 GeeksforGeeks ( https://www.geeksforgeeks.org/indexing-in-databases-set-1/ ),为聚集索引创建索引文件。有一个图表显示具有学期 1-8 的索引文件。
但是在阅读https://use-the-index-luke.com/blog/2014-01/unreasonable-defaults-primary-key-clustering-key时,提到了
如果一个表有聚集索引,基本上意味着索引就是这个表
我想知道在聚集索引和非聚集索引中是否生成索引文件?
另外,我们可以看到表上的索引文件,即它存储的内容吗?
解决方案
MySQL 本质上只有一种索引方法:BTree。(是的,还有空间和全文,但这是另一个讨论。)
一旦你了解了 BTree 的工作原理(参见 Wikipedia),我们就可以讨论进入 InnoDB 中叶节点的内容。
情况 1:“数据”BTree 包含所有列,并根据PRIMARY KEY
. 在 MySQL 中,PK根据定义是“UNIQUE”和“Clustered”。(其他供应商有其他选择。)
情况 2:“辅助”INDEX
存储在单独的 BTree 中。叶节点中有 (1) 二级索引中定义的列,以及 PK 列的副本。要完成SELECT
使用二级索引,必须先使用索引 BTree 获取 PK,然后通过数据 BTree 获取数据。(如果索引是“覆盖”,则不需要这第二步。)
MySQL 中没有“Rownum”。
BTrees 实际上是 B+Trees,从而使范围扫描更有效。
InnoDB 将给定表的所有 BTree(一个用于数据+PK,一个用于每个二级索引)放入某个表空间。表空间是通用的(ibdata1
文件)、特定于表的(文件tablename.ibd
)或(在较新版本中)可以包含多个表的“表空间”文件。
警告:我所描述的适用于 MySQL 的 InnoDB,并且可能不适用于任何其他引擎。
我不知道有什么好工具可以在不深入细节的情况下检查 InnoDB 的 BTree。对于 Percona 版本:
SELECT i.INDEX_NAME as Index_Name,
IF(ROWS_READ IS NULL, 'Unused',
IF(ROWS_READ > 2e9, 'Overflow', ROWS_READ)) as Rows_Read
FROM (
SELECT DISTINCT TABLE_SCHEMA, TABLE_NAME, INDEX_NAME
FROM information_schema.STATISTICS
) i
LEFT JOIN information_schema.INDEX_STATISTICS s
ON i.TABLE_SCHEMA = s.TABLE_SCHEMA
AND i.TABLE_NAME = s.TABLE_NAME
AND i.INDEX_NAME = s.INDEX_NAME
WHERE i.TABLE_SCHEMA = ?
AND i.TABLE_NAME = ?
ORDER BY IF(i.INDEX_NAME = 'PRIMARY', 0, 1)
对于 MySQL(甲骨文):
SELECT last_update,
n_rows,
'Data & PK' AS 'Type',
clustered_index_size * 16384 AS Bytes,
ROUND(clustered_index_size * 16384 / n_rows) AS 'Bytes/row',
clustered_index_size AS Pages,
ROUND(n_rows / clustered_index_size) AS 'Rows/page'
FROM mysql.innodb_table_stats
WHERE ( ( database_name = ? AND table_name = ? )
OR ( database_name = LOWER(?) AND table_name = LOWER(?)
UNION
SELECT last_update,
n_rows,
'Secondary Indexes' AS 'BTrees',
sum_of_other_index_sizes * 16384 AS Bytes,
ROUND(sum_of_other_index_sizes * 16384 / n_rows) AS 'Bytes/row',
sum_of_other_index_sizes AS Pages,
ROUND(n_rows / sum_of_other_index_sizes) AS 'Rows/page'
FROM mysql.innodb_table_stats
WHERE ( ( database_name = ? AND table_name = ? )
OR ( database_name = LOWER(?) AND table_name = LOWER(?)
AND sum_of_other_index_sizes > 0
推荐阅读
- visual-studio-code - 在 VS Code 中为 Lerna 项目调试 Jest 测试
- xamarin - MVVM Cross android 方向问题
- c# - GroupBy 有或没有总和
- android - 如何获得有限的编号。回收站视图中的数据
- sql-server - 数据库角色可以通过它无权访问的存储过程访问表
- c# - 使用 Docker 从开发到生产的不同转换日期
- boost-python - 如何在 ubuntu 系统上安装 boost_python-py38
- codeigniter - Codeigiter 多次登录,会话在 Centos 服务器上与 Cpanel 混淆
- c - 用大括号括起来的结构是什么意思?
- django - 在 django 中发送(发件人)邮件配置