【问题标题】:How to make this query efficient?如何使这个查询高效?
【发布时间】:2016-04-26 08:57:08
【问题描述】:

我有一个非常复杂的 SQL 查询,多亏了 index.html,它大部分运行良好。但是,我似乎无法加快 JOIN。

简化很多,可能是这样的:

主表:id INT; 表参考:type INT, id1 INT, id2 INT;

换句话说,一个主表有一个 id 字段,另一个表有两个字段 id1 和 id2。 对于我感兴趣的某些类型值(例如 t1 和 t2),id1 和 id2 都是对主表的引用。

查询;

SELECT main.id
     , ref.id2 FROM main
  LEFT 
  JOIN ref 
 ON ref.type = t1 
    OR ref.type = t2 
   AND (main.id = ref.id1 OR main.id = ref.id2) 
 WHERE main.id IN (list) 
    OR main.id = ref.id1 
    OR main.id = ref.id2

在自然语言中: 我有一个 ID 列表。我想要所有这些 id,并且对于该列表中的每个 id1 或 id2,我想要相关的。

一个例子。有以下数据:

主要:

  • 1..20

参考:

  • (1, 15)

  • (20, 2)

  • (3, 5)

  • (12, 17)

列表:

  • 1..5

我想检索(以任何顺序):

  • 1
  • 2
  • 3
  • 4
  • 5
  • 15
  • 20

我尝试了几个我认为可以提供帮助的索引:(type, id1), (type, id2), (type, id1, id2);但无济于事。解释说它正在使用它们,但没有明显的区别。

一旦每个表有几千行,如果没有列表部分,它需要大约一秒的时间。对于一些(大的,数百个元素)列表,它似乎需要更多。

为什么要花这么多时间?有没有可能让它更快?

我希望没关系,但我使用的是 MariaDb 10.0.16

【问题讨论】:

  • 你必须WHERE 子句,但没有ON 子句...
  • OR-ed join 条件通常会导致糟糕的计划,最好重写为两个 Selecta 加上UNION
  • 什么是t1t2,列或参数?
  • 我不理解外部查询中的or 子句。如果您有感兴趣的 id 列表,为什么还要更多?
  • 您应该显示一些实际数据,以便更好地解释您尝试实现的目标。

标签: mysql sql indexing query-optimization mariadb


【解决方案1】:

如果不了解您的系统的很多细节,就很难给出性能建议。不过,这是一种替代方法,它可能会或可能不会表现更好:

SELECT id FROM main WHERE id IN (1, 2, 3, 4, 5)
UNION
SELECT id2 FROM refs WHERE id1 IN (1, 2, 3, 4, 5)
UNION
SELECT id1 FROM refs WHERE id2 IN (1, 2, 3, 4, 5)

【讨论】:

  • 谢谢。我希望能找到一些明显我做错的事情。我没想过使用 UNION,猜想这会有所帮助。
  • 查询比提供的示例复杂得多,因此更改比我预期的要困难得多,但是使用 UNIONS 运行速度要快一个数量级(无论如何,使用我当前的数据)。它还帮助我发现了一个令人讨厌的错误。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-23
  • 2013-02-10
相关资源
最近更新 更多