我有一个查询,其中一个表有大约1000万行,另外两个表在每个表中<20。
SELECT a.name, b.name, c.total
FROM smallTable1 a, smallTable2 b, largeTable c
WHERE c.id1 = a.id AND c.id2 = b.id;
largeTable
包含(id, id1, id2, total)
列和〜1000万行
smallTable1
列(id, name)
smallTable2
列(id, name)
现在需要5秒才能运行 有可能让它更快吗?
答案 0 :(得分:2)
创建索引 - 它们是查询速度快的原因。如果没有索引,我们将无法使用仅限CPU的解决方案。
所以:
重要:您可以同时为多个列创建索引,例如此LargeTable(id1,id2)&lt; ---不要这样做,因为它没有意义你的情况。
下一步,您的查询不是开箱即用的错误,但它不符合查询的最佳做法。关系数据库基于Set theory。因此,你必须考虑“带有弹珠的袋子”而不是“桌子中的细胞”。 粗略地说,您的初始查询转换为:
Ambrish建议了正确的查询,使用它虽然这不会更快。
为什么呢?因为最后,您仍然将表中的所有数据从数据库中提取出来。
至于数据本身就是:1000万条记录并不是一张大得惊人的大表,但它也不小。在数据仓库中,star schema是标准。而且你基本上有一个星型模式。您实际面临的问题是必须在运行中计算结果并且需要时间。我告诉你的原因是因为在企业环境中,工程师每天都面临这个问题。解决方案是OLAP(基本上是预先计算,预先聚合,预先汇总,预先存在的所有数据)。然后最终用户只查询这个预先计算的数据并且查询看起来非常快,但它永远不会100%正确,因为OLTP之间存在延迟(在线事务性处理=日常数据库)和OLAP(在线分析处理=报告数据库) 这些索引将有助于查询WHERE id = 3等。但是当你交叉加入并基本上从数据库中提取所有内容时,它可能不会在你的情况下发挥重要作用。
所以长话短说:如果您的唯一选择是查询,那么很难做出改进。
答案 1 :(得分:0)
在一种情况下,大表中的单独索引ID1
和ID2
会产生较小的差异。如果有{9}}匹配ID1
的9,000,000行和匹配SmallTable1.id
的{{1}}的200行,而200是同时存在的唯一行,则您将仍在做几乎完整的表/索引扫描。如果是这种情况,在 {/ em> ID2
和 SmallTable2.id
上创建索引应该可以加快速度,因为它可以找到带有索引的200行寻道。
如果可行,您可能希望在该索引中包含ID1
,以使其成为该表的覆盖索引。
这个解决方案(假设它是一个)将是非常以数据为中心的,因此如果数据发生显着变化,执行将会改变。
无论您决定做什么,我建议您进行一次更改(创建索引或其他),然后检查执行计划。进行另一项更改并检查执行计划。进行另一项更改并检查执行计划。根据需要重复或倒回。
答案 2 :(得分:-1)
使用join而不是WHERE
子句
SELECT a.name, b.name, c.total
FROM smallTable1 a join largeTable c on c.id1 = a.id
join smallTable2 b on c.id2 = b.id;
在index
和largeTable(id1)
largeTable(id2)