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。)