0

我有一个类似的表'tbl': ID bigint(20) - 主键,自动增量字段 1 字段 2 字段 3

该表有 600k+ 行。

  1. 查询:SELECT * from tblORDER by ID LIMIT 600000, 1 耗时 1.68 秒
  2. 查询:SELECT ID, field1 from tblORDER by ID LIMIT 600000, 1 耗时 1.69 秒
  3. 查询:SELECT ID from tblORDER by ID LIMIT 600000, 1 耗时 0.16 秒
  4. 查询:SELECT * from tblWHERE ID = xxx 耗时 0.005 秒

这些查询在 phpmyadmin 中进行了测试。

结果是查询 3 和查询 4 ​​一起返回必然的数据。查询 1 执行相同的工作,但速度要慢得多......

这看起来不适合我。谁能给点建议?

PS我很抱歉格式化..我是这个网站的新手。

新测试:

Q5 : CREATE TEMPORARY TABLE tmptable AS (SELECT ID FROM tblWHERE ID LIMIT 600030, 30); SELECT * FROM tblWHERE ID IN (SELECT ID FROM tmptable); 耗时 0.38 秒

我仍然不明白这怎么可能。我重新创建了所有索引。我还能用那个表做什么?手动删除并重新填充?:)

4

1 回答 1

4

查询 1 查看表的主键索引,找到正确的 600,000 个 id 及其在表中的相应位置,然后转到表并从这 600k 位置获取所有内容。

查询 2 查看表的主键索引,找到正确的 600k id 及其在表中的相应位置,然后转到表并从这 600k 行中获取请求的任何字段子集。

查询 3 查看表的主键索引,找到正确的 600k id,然后返回它们。它根本不需要看表。

查询 4 ​​查看表的主键索引,找到请求的单个条目,转到表,读取该单个条目,然后返回它。

在时间方面,让我们向后构建:

(Q4) 表索引允许在 O(log n) 时间内查找键 (id),这意味着每次表的大小翻倍时,只需一个额外的步骤即可在索引中找到键*。如果您有 100 万行,那么只需大约 20 步即可找到它。十亿行?30 步。索引条目包括有关在表中的何处查找该行的数据的数据,因此 MySQL 跳转到表中的该位置并读取该行。为此报告的时间几乎完全是开销。

(Q3) 正如我所提到的,表索引非常快;此查询找到第一个条目并遍历树,直到它具有请求的行数。我确信我可以计算出它需要的精确步数,但我们最多会说 20 步 x 600k 行 = 12M 步;因为它正在遍历一棵树,所以它可能更像是 1M 步,但确切的数字在很大程度上是无关紧要的。这里要意识到的最重要的事情是,一旦 MySQL 遍历索引以提取所需的 id,它就会拥有您所要求的一切。没必要去看表。为这个报告的时间本质上是 MySQL 遍历索引所花费的时间。

(Q2) 这与查询 3 中讨论的相同的树遍历开始,但是在提取所需的 ID 时,MySQL 还提取它们在表文件中的位置。然后它必须转到表文件(可能已经mmap在内存中缓存/ ped),并且对于它提取的每个条目,寻找表中的适当位置并从这些行中获取请求的字段。此查询报告的时间是遍历索引所花费的时间(如在 Q3 中)加上访问索引中指定的每一行的时间。

(Q1) 当指定所有字段时,这与 Q2 相同。由于时间与第二季度基本相同,我们可以看到从数据库中提取更多字段并不会真正花费更多时间,任何时候都比爬取索引和查找行相形见绌。

*:大多数数据库使用的索引数据结构( MySQL的 B-trees)具有远高于 2 的日志基数,这意味着每次表翻倍时都不是额外的步骤,而更像是每次表大小时的额外步骤增加了数百到数千倍。这意味着不是我在示例中说明的 20-30 个步骤,而是更像 2-5 个步骤。

于 2013-06-27T03:05:15.900 回答