我有一张桌子'tbl'是这样的: ID bigint(20) - 主键,自动增量 FIELD1 域2 字段3
该表有600k +行。
tbl
ORDER by ID LIMIT 600000,1需要1.68秒tbl
的字段1按ID LIMIT 600000 ORDER,1需要1.69秒tbl
的订单ID由ID LIMIT 600000订购,1需要0.16秒tbl
WHERE ID = xxx需要0.005秒这些查询在phpmyadmin中进行测试。
结果是查询3和查询4一起返回必要的数据。 查询1执行相同的工作,但速度要慢得多......
这对我来说不合适。 有人可以提出任何建议吗?
P.S。我很抱歉格式化..我是这个网站的新手。
新测试:
Q5:CREATE TEMPORARY TABLE tmptable AS(SELECT ID FROM tbl
WHERE ID LIMIT 600030,30);
SELECT * FROM tbl
WHERE ID IN(SELECT ID FROM tmptable);需要0.38秒
我仍然不明白它是如何可能的。我重新创建了所有索引..我还可以用该表做什么?手动删除并重新填充? :)
答案 0 :(得分: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步×600k行= 12M步;因为它遍历了一棵树,所以它可能更像1M步骤,但确切的数字在很大程度上是无关紧要的。这里要认识到的最重要的事情是,一旦MySQL走了索引以拉动它需要的ID,它就会有你要求的一切。没有必要去看表。报告的时间基本上是MySQL走索引的时间。
(Q2)这从与查询3讨论的相同的树步行开始,但在提取所需的ID时,MySQL也会在表文件中提取它们的位置。然后它必须转到表文件(可能已在内存中缓存/ mmap
ped),并且对于它所提取的每个条目,寻找表中的适当位置并从这些行中获取所请求的字段。报告此查询的时间是走索引所需的时间(如Q3中所示)加上访问索引中指定的每一行的时间。
(Q1)当指定所有字段时,这与Q2相同。由于时间基本上与Q2相同,我们可以看到,实际上并没有花费更多的时间从数据库中提取更多字段,只要通过爬行索引并寻找行就相形见绌。
*:大多数数据库使用索引数据结构(MySQL B-trees),其日志基数远高于2,这意味着每次表加倍时,不是额外的步骤,而是更像是一个额外的步骤每次表格大小上升几百到几千。这意味着,与示例中所述的20-30步不同,它更像是2-5。