1

我的问题涉及关系数据库访问数据的方式,以及使用仅索引扫描的特殊情况,即扫描检查所有“位置”条件并从某个索引中获取所有返回值,而不访问表本身。

  1. 想象一下,我们需要访问一些不在索引中的列。我们需要出于以下两个原因之一(或两者)访问它们:与“where”子句进行比较并获取列值作为结果。在这种情况下,数据库将如何操作:它会获取整行,还是只获取它需要的列?

  2. 由于第一个问题出现了这个问题:如果我们不使用 Index-Only-Scan,选择查询中返回的列数真的很重要吗?我的意思是,如果我们必须获取或与 'where' 子句比较某些未索引的列 - 我们返回多少列真的很重要,或者我们可以编写“select * from ...”而不用担心数据库获取反正整行?

  3. 当我们使用 Index-Only-Scans 时,我们必须将查询处理的所有列包含在一个索引中。如果某个列包含在另一个索引中 - 这不会破坏性能。我对吗?

  4. 我读过 MySQL InnoDB 引擎默认使用聚集索引,即表中的所有行都按某个索引进行物理排序。这意味着使用某个二级索引搜索该表的效率会降低,因为在该搜索之后,db 必须在主索引上创建第二个,因为在聚集索引中,db 不再存储 rowId。我对吗?如果是,为什么 MySQL 会以这种方式实现索引,从而限制二级索引的使用?

4

1 回答 1

1

其中一些解释可能会涵盖您已经知道的内容,但完整的细节可能会对未来的读者有所帮助。

  1. 服务器很可能只获取所需的行。但是,这可能会受到数据存储方式的影响。例如,InnoDB 引擎通常存储大数据(如TEXTs 和BLOBs 离页,因此如果不需要,可能不会获取这些数据。

  2. 我想我需要在这里澄清一下,所以如果我从你的问题中遗漏了什么,请纠正我。首先,最好只返回您需要的列并列出所有列而不是选择*更快。与 #1 一样,选择其他列会有多大的不同取决于。选择大列(如TEXTs 或BLOBs)通常比小列更昂贵。

  3. 我不是 100% 确定你在这里的意思,但我想我可以回答这个问题。如果您有类似的查询,则类似SELECT c1, c2, c3 FROM table WHERE c1 = 1 AND c2 = 2的索引(c1,c2,c3)可能是最佳的;查询需要的所有列都在索引中,因此服务器不需要查找完整的数据行。c1c2c3是否包含在任何其他索引中都没有关系。

  4. 在您的问题中,您说的是a clustered index db is not storing the rowId anymore,这并不完全正确。

    假设rowId是数据的唯一标识符,可能是数字标识符:

    在非集群数据库表中,所有索引都将某些列连接到物理数据位置。在主索引的情况下,这看起来像rowId -> data location。二级索引可能看起来像column 1 -> column 2 -> data location. 为了获取任何其他数据,服务器然后根据物理位置查找数据。

    在聚簇表中,物理数据基本上就是主索引。主索引看起来像rowId -> data,二级索引看起来像column 1 -> column 2 -> rowId

    对于非聚集表,完整的查找路径看起来像rowId -> data location -> data使用主索引和column 1 -> column 2 -> data location -> data二级索引。

    对于聚簇表,它看起来像rowId -> data主索引和column 1 -> column 2 -> rowId -> data二级索引。

    因此,为了更正本节开头的引用,真正“存储”的唯一索引rowId是聚簇表上的二级索引。

    虽然聚簇表上的二级索引查找比非聚簇表慢,但如果您使用短主键,差异通常可以忽略不计。聚集表的主要好处之一是主索引查找速度更快,因此如果您主要使用主键查找,它们是有益的。

回应 KutaBeach 的评论:

获取不需要的列没有帮助。当服务器需要获取数据以获取不在索引中的行时,它并不总是获取该行的所有数据。一些存储配置将一些数据存储在主行之外,因为它可能非常大,否则会影响性能。一个示例可以是TEXT每行长度为 65535 个字符的列。TEXT如果存储引擎将该数据存储在页面外,那么在不需要列的情况下 从行获取数据会快得多。

听起来当您说 时rowId,您的意思是行的物理地址,而不是分配给每行的唯一编号。在这种情况下,您是正确的,只有聚集表上的二级索引不存储rowId; 所有其他索引都存储rowId. 然而,这并不是因为数据可以或不能移动;表中的数据可以随时移动,在这种情况下,索引会更新以反映移动。在 MySQL 中,aPRIMARY INDEX基本上只是表的主索引。它与索引几乎相同,UNIQUE因为它强制值是唯一的,唯一的区别是它用作表的主键。非聚集索引确实包含每个rowId.

于 2013-04-01T14:50:59.860 回答