Marcus Asked: 2016-06-16 05:26:22 +0800 CST2016-06-16 05:26:22 +0800 CST 2016-06-16 05:26:22 +0800 CST 在哪些情况下全表扫描优于低基数索引扫描? 772 是否存在执行 FTS 比扫描基数非常低的索引更可取的真实场景?为什么 MySQL 会这样做? 索引扫描不总是涉及读取较少的数据(页面)吗? mysql index-tuning 1 个回答 Voted Best Answer Rick James 2016-06-28T21:51:34+08:002016-06-28T21:51:34+08:00 让我们想象一个大表,索引本质上是编号的行。我们希望每 50 行通过id IN (50,100,150,200, ...). 此外,假设每个块大约有 100 行。 如果进行表扫描,它将读取所有块。该扫描将读取一个块,拾取 2 行,移动到下一个块,等等。到它完成时,它将读取每个块一次。如果使用索引,会在索引和数据之间来回跳动;这个稍微差一点。尽管如此,在移动到下一个块之前,一个块将产生 2 行。 现在,让我们稍微改变一下例子。假设这些行是由其他东西排序的。现在 50 和 100 很可能在不同的块中,等等。此外,假设该表至少是缓存的两倍。 在这种情况下,使用索引将(通常)抓取一个块,从中提取一行,将块保留在缓存中。但是,在请求该块中的另一行之前,该块可能会从缓存中弹出。也就是说,所有的块都会被读取两次。表扫描的速度将是原来的两倍,因为它只需要读取块一次,本质上与第一种情况一样。 (使用 UUID、GUID、MD5 或 SHA1 作为 PRIMARY KEY 是产生此问题的简单方法。)
让我们想象一个大表,索引本质上是编号的行。我们希望每 50 行通过
id IN (50,100,150,200, ...)
. 此外,假设每个块大约有 100 行。如果进行表扫描,它将读取所有块。该扫描将读取一个块,拾取 2 行,移动到下一个块,等等。到它完成时,它将读取每个块一次。如果使用索引,会在索引和数据之间来回跳动;这个稍微差一点。尽管如此,在移动到下一个块之前,一个块将产生 2 行。
现在,让我们稍微改变一下例子。假设这些行是由其他东西排序的。现在 50 和 100 很可能在不同的块中,等等。此外,假设该表至少是缓存的两倍。
在这种情况下,使用索引将(通常)抓取一个块,从中提取一行,将块保留在缓存中。但是,在请求该块中的另一行之前,该块可能会从缓存中弹出。也就是说,所有的块都会被读取两次。表扫描的速度将是原来的两倍,因为它只需要读取块一次,本质上与第一种情况一样。
(使用 UUID、GUID、MD5 或 SHA1 作为 PRIMARY KEY 是产生此问题的简单方法。)