2

我有 2 个大约 3000/4000 行的表。我需要使用 Left Join 建立关系,以通过搜索文本或日期时间来过滤结果。我还需要计算分页的总行数。当我运行查询时速度非常慢,请考虑通过控制台大约 40/45 秒和网页超过一分钟。关系是:对于表 A 的 1,表 B 中有 N。有快速查询的解决方案吗?示例查询是:

SELECT X,Y,Z, (SELECT COUNT(*) 
     FROM tableB WHERE tableB.idTa=tableA.id) AS CountTB 
FROM tableA 
LEFT JOIN tableB ON tableA.id = tableB.idA
WHERE tableA.X LIKE'%mytext%' OR tableB.Z LIKE'%mytext%' 
GROUP BY tableA.id 
ORDER BY tableA.Y LIMIT 0,10

谢谢你们

当然存在 ON 子句。只是从我的手机打错了。现在它是正确的并且非常慢:)

新更新:如果我将关系从 LEFT JOIN 更改为 RIGHT JOIN,它会变得非常快......为什么?

4

3 回答 3

2

从正确开始,JOIN我相信应该会很快工作。

就像是:

SELECT a.X,a.Y,a.Z, COUNT(b.id)  CountTB 
FROM tableA a
LEFT JOIN tableB b
ON b.idTa = a.id AND b.Z LIKE'%mytext%' 
WHERE a.X LIKE '%mytext%'
GROUP BY tableA.id 
ORDER BY tableA.Y LIMIT 0,10

你的条件不是很清楚。如果你能提供好的数据样本,我们可以找到更好的查询。

我猜你不需要b.Z LIKE'%mytext%'。从刚刚开始:

SELECT a.X,a.Y,a.Z, COUNT(b.id)  CountTB 
FROM tableA a
LEFT JOIN tableB b
ON b.idTa = a.id 
WHERE a.X LIKE '%mytext%'
GROUP BY tableA.id 
ORDER BY tableA.Y LIMIT 0,10
于 2016-06-28T14:15:23.020 回答
1

对此进行猛烈抨击,只是为了向您指明大方向,这是该查询的可能重写:(我不保证它有效......)

SELECT X,Y,Z, COUNT(B.id) AS CountTB
FROM tableA A
  LEFT JOIN tableB B
    USING (id)
WHERE tableA.X LIKE'%mytext%' OR tableB.Z LIKE'%mytext%' 
GROUP BY X, Y, Z
ORDER BY tableA.Y 
LIMIT 0,10

注意我的许多变化:

  1. 没有嵌套查询。
  2. 为方便起见,这些表由别名A和标识B
  3. LEFT JOINis是的USING (id)简写WHERE A.id = B.id
  4. GROUP BY子句指定数据将按这三个变量进行分组。所有这些都必须出现在SELECT子句中,并且出现的其他所有内容必须是聚合函数,例如COUNT()or SUM()

同样,我不保证此查询有效。 但它应该说明通常应该如何构造这样的查询。

于 2016-06-28T14:20:34.133 回答
0

LEFT除非你想NULLs从“右手”表中使用,否则不要使用。在这种情况下,我认为您不会这样做。

定位( SELECT COUNT... )意味着它需要永远重新评估,它不需要。摆脱它;使用SQL_CALC_FOUND_ROWS.

AX 和 BZ 正在搜索相同的子字符串?它们总是具有相同的值吗?如果是这样,那么只搜索其中一个。(LIKE '%...'是您查询中代价高昂的部分。)

使用JOIN会增加行数;然后你加GROUP BY了放气。这种膨胀/放气成本很高。

无法按“%mytext% ”COUNT(*)过滤,因此它不会为您提供“第 30-39 行,共 145 行”所需的内容。

是AZ还是BZ??

SELECT SQL_CALC_FOUND_ROWS
        a.X, a.Y,
        ( SELECT Z FROM tableB WHERE idTa = a.id AND Z LIKE'%mytext%' ) AS Z
    FROM tableA AS a
    WHERE a.X LIKE '%mytext%'
    ORDER BY a.Y
    LIMIT 0,10

SELECT FOUND_ROWS();   -- to get the "of 156 rows"

你需要这些

tableB: INDEX(idTa)
tableA: INDEX(Y)

警告:由于不清楚 A 和 B 之间的关系是什么(1:many vs many:many),这个解决方案可能是不正确的。子查询返回多行会跳出错误。

所以,我可能没有给你“正确”的答案,但希望我已经给了你足够的线索,这样你就可以更接近了。

在那之后,也许你可以通过“记住你离开的地方”来加快分页速度,而不是使用OFFSET. 见我的博客

如果您想进一步讨论这个问题,请提供SHOW CREATE TABLE并且不要混淆列名——通常这些名称会提供您意图的线索。

于 2016-07-01T16:34:43.333 回答