关系数据库如何获取未编制索引的列?

时间:2013-04-01 10:27:31

标签: mysql sql indexing

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

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

  2. 由于第一个问题出现了这个问题:如果我们不使用Index-Only-Scan,那么在select查询中返回的列数是否真的很重要?我的意思是,如果我们必须使用'where'子句获取或比较一些未编入索引的列 - 我们返回的列数确实很重要,或者我们可以编写“select * from ...”而无需担心数据库提取整个行呢?

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

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

1 个答案:

答案 0 :(得分:1)

其中一些解释可能会超出您已经知道的内容,但详细信息可能有助于未来的读者。

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

  2. 我想我需要澄清一下,如果我遗漏了你的问题,请纠正我。首先,最好只返回所需的列并列出所有列,而不是选择*更快。与#1一样,选择其他列的差异将取决于多少。选择大列(例如TEXTBLOB)通常比小列更昂贵。

  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的唯一索引是聚簇表上的二级索引。

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

  5. 回应KutaBeach的评论:

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

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