MySQL 中的聚簇索引
Clustered Indexing in 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时,提到了
If a table has a clustered index, it basically means the index is the table
我想知道在聚集索引和非聚集索引中是否生成索引文件?
此外,我们可以看到 table 上的索引文件,即它存储的内容吗?
MySQL 本质上有一种索引方法:BTree。 (是的,还有 Spatial 和 Fulltext,但那是另一个讨论。)
一旦您理解了 BTree 的工作原理(请参阅维基百科),我们就可以讨论 InnoDB 中叶节点的内容。
情况1:"data" BTree包含所有列,并根据PRIMARY KEY
排序。在MySQL中,PK根据定义、"UNIQUE"和"Clustered"。 (其他供应商有其他选择。)
情况2:一个'secondary' INDEX
存储在一个单独的BTree中。叶节点中有 (1) 二级索引中定义的列,以及 PK 列的副本。要使用二级索引完成一个SELECT
,它必须首先使用索引BTree 获取PK,然后通过数据BTree 获取数据。 (如果索引为"covering",则不需要第二步。)
MySQL中没有"Rownum"。
BTrees实际上是B+树,从而使范围扫描更加高效。
InnoDB 将给定 table 的所有 BTree(一个用于数据+PK,一个用于每个二级索引)放入某个 table 空间。 table 空间是通用空间(ibdata1
文件)、table 特定空间(文件 tablename.ibd
)或(在较新版本中)"tablespace" 文件,可以包含多个 tables.
警告:我所描述的适用于 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
I want to know whether an index file is generated in clustered index and non clustered index or not ?
MySQL 中的 InnoDB table(默认引擎类型)始终是集群的。这意味着索引存储所有 table 列;不需要单独的 "heap" table。如果您使用旧的 MyIsam 引擎,那么 table 会有一个堆,再加上它上面的任何额外索引。
Also , can we see the index file on a table ,i.e, what it stores ?
"primary" 索引存储table 的所有列:键列和非键列。 "Secondary" 索引可以更有选择性,只存储列的一个子集;但是第一个什么都有。
从 MySQL 用户的角度来看,聚簇索引业务是一个实现细节。
table 中的信息必须存储在 SSD 或硬盘驱动器等存储设备上的某个位置。很大程度上取决于数据库服务器的版本和使用的特定访问方法(InnoDB、MyISAM 等)。
一些信息是元数据:table 的描述。 MySql 通常将其存储在 table.frm
文件中。行中的信息通常存储在容器文件 tablename.ibd
中。这些文件只能由 MySQL 服务器或为此目的构建的其他软件解释;典型的独立程序无法理解它们 尤其是 如果 MySQL 服务器处于活动状态。换句话说:如果您编写程序来更改任何这些文件,您 将 破坏您的数据库并丢失 table 的内容。
容器文件中有一些数据结构,由MySQL的访问方法代码访问。通常 table 具有主键的存储就像它们是索引一样,每行的所有数据都挂在每个索引条目上。该数据结构是 聚集索引。
您不一定要查看机器 运行 和 MySQL 服务器的文件系统并指向包含索引、聚簇索引或其他内容的特定文件。使用 InnoDB,您可以指示 MySQL 使用 TABLESPACE commands 将数据放入文件系统中的特定文件中。但是从 MySQL 8 开始,无法将索引放在自己的 tablespace.
中
(Oracle 和 MS SQL 服务器企业版等产品的数据库管理员通过将 tablespace 移动到不同的磁盘驱动器来优化和并行访问。这不像在 MySQL 中很重要,直到您的 table 开始占用磁盘驱动器的很大一部分 space。)
我正在学习数据库中的索引。 根据 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时,提到了
If a table has a clustered index, it basically means the index is the table
我想知道在聚集索引和非聚集索引中是否生成索引文件?
此外,我们可以看到 table 上的索引文件,即它存储的内容吗?
MySQL 本质上有一种索引方法:BTree。 (是的,还有 Spatial 和 Fulltext,但那是另一个讨论。)
一旦您理解了 BTree 的工作原理(请参阅维基百科),我们就可以讨论 InnoDB 中叶节点的内容。
情况1:"data" BTree包含所有列,并根据PRIMARY KEY
排序。在MySQL中,PK根据定义、"UNIQUE"和"Clustered"。 (其他供应商有其他选择。)
情况2:一个'secondary' INDEX
存储在一个单独的BTree中。叶节点中有 (1) 二级索引中定义的列,以及 PK 列的副本。要使用二级索引完成一个SELECT
,它必须首先使用索引BTree 获取PK,然后通过数据BTree 获取数据。 (如果索引为"covering",则不需要第二步。)
MySQL中没有"Rownum"。
BTrees实际上是B+树,从而使范围扫描更加高效。
InnoDB 将给定 table 的所有 BTree(一个用于数据+PK,一个用于每个二级索引)放入某个 table 空间。 table 空间是通用空间(ibdata1
文件)、table 特定空间(文件 tablename.ibd
)或(在较新版本中)"tablespace" 文件,可以包含多个 tables.
警告:我所描述的适用于 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
I want to know whether an index file is generated in clustered index and non clustered index or not ?
MySQL 中的 InnoDB table(默认引擎类型)始终是集群的。这意味着索引存储所有 table 列;不需要单独的 "heap" table。如果您使用旧的 MyIsam 引擎,那么 table 会有一个堆,再加上它上面的任何额外索引。
Also , can we see the index file on a table ,i.e, what it stores ?
"primary" 索引存储table 的所有列:键列和非键列。 "Secondary" 索引可以更有选择性,只存储列的一个子集;但是第一个什么都有。
从 MySQL 用户的角度来看,聚簇索引业务是一个实现细节。
table 中的信息必须存储在 SSD 或硬盘驱动器等存储设备上的某个位置。很大程度上取决于数据库服务器的版本和使用的特定访问方法(InnoDB、MyISAM 等)。
一些信息是元数据:table 的描述。 MySql 通常将其存储在 table.frm
文件中。行中的信息通常存储在容器文件 tablename.ibd
中。这些文件只能由 MySQL 服务器或为此目的构建的其他软件解释;典型的独立程序无法理解它们 尤其是 如果 MySQL 服务器处于活动状态。换句话说:如果您编写程序来更改任何这些文件,您 将 破坏您的数据库并丢失 table 的内容。
容器文件中有一些数据结构,由MySQL的访问方法代码访问。通常 table 具有主键的存储就像它们是索引一样,每行的所有数据都挂在每个索引条目上。该数据结构是 聚集索引。
您不一定要查看机器 运行 和 MySQL 服务器的文件系统并指向包含索引、聚簇索引或其他内容的特定文件。使用 InnoDB,您可以指示 MySQL 使用 TABLESPACE commands 将数据放入文件系统中的特定文件中。但是从 MySQL 8 开始,无法将索引放在自己的 tablespace.
中(Oracle 和 MS SQL 服务器企业版等产品的数据库管理员通过将 tablespace 移动到不同的磁盘驱动器来优化和并行访问。这不像在 MySQL 中很重要,直到您的 table 开始占用磁盘驱动器的很大一部分 space。)