【问题标题】:SQL performance hit when NOT joining不加入时 SQL 性能下降
【发布时间】:2014-08-29 04:50:28
【问题描述】:

我正在尝试对一个相当简单(但很大)的表执行选择查询,当我加入某个辅助表时,性能会降低 10 倍以上。

TableA 以“ID1”和“ID2”两列为键,共有 10 个数字 (int + dbl) 列。

TableB 以“ID1”为键,共有 2 个数字 (int) 列。

SELECT
    AVG(NULLIF(dollarValue, 0))
FROM
    TableA
INNER JOIN
    TableB
ON
    TableA.ID1 = TableB.ID1
WHERE
    TableA.ID2 = 5
AND
    TableA.ID1 BETWEEN 15000 AND 20000

一旦移除连接,性能就会受到重大影响。上面的查询需要 0.016 秒 才能运行,而下面的查询需要 0.216 秒 才能运行。

最终目标是用 TableB 的第二(非键)列替换 TableA 的“ID1”并弃用 TableB。

SELECT
    AVG(NULLIF(dollarValue, 0))
FROM
    tableA
WHERE
    ID2 = 5
AND
    ID1 BETWEEN 15000 AND 20000

两个表的主键都有索引。两个表之间的关系是一对多的。数据库引擎是 MyISAM。

场景 1(快速):

id  stype   table   type    possKey key     kln ref                     rws extra
1   SIMPLE  TableB  range   PRIMARY PRIMARY 4                           498 Using where; Using index
1   SIMPLE  TableA  eq_ref  PRIMARY PRIMARY 8   schm.TableA.ID1,const   1   

场景 2(慢):

id  stype   table   type    possKey key     key_len ref         rows    extra
1   SIMPLE  TableA  range   PRIMARY PRIMARY 8                   288282  Using where

场景 2 中的行数和没有提及索引的情况确实很突出,但为什么会这样呢?

两个查询的 700 个结果 -- 相同的数据。

【问题讨论】:

标签: mysql sql performance select join


【解决方案1】:

鉴于您的查询,我认为这样的索引可能有用:

CREATE INDEX i ON tableA(ID2, ID1)

first 查询速度更快的一个可能原因是,tableB 中可能只有很少的记录,这使得连接谓词与范围谓词相比非常有选择性。

I suggest reading up on indexes。了解它们的 2-3 个细节将帮助您轻松调整查询,只需选择更好的索引。

【讨论】:

  • 以相反的顺序(ID2、ID1——而不是 ID1、ID2)添加索引与键列完美。没错,TableA 包含 6,400,000 条记录,而 TableB 只有 13,000 条记录。您能否解释一下切换索引中列的顺序如何产生与在较小表上连接的相同好处?是否与两个订单中都有两个索引有关?
  • @KillerHurdz:似乎ID2 = 5ID1 BETWEEN 15000 AND 20000 更具选择性。这意味着在搜索索引的 B-Tree 时,可以首先通过过滤ID2 选择更小的数据集,然后通过过滤进一步稍微 ID1。如果您反转列,那么您将首先将大量数据从磁盘加载到内存中,然后才显着减少它。 This page 有很多见解
猜你喜欢
  • 1970-01-01
  • 2012-07-02
  • 2010-11-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-21
  • 1970-01-01
  • 2013-05-10
相关资源
最近更新 更多