簡體   English   中英

MySql Left Join查詢非常慢

[英]MySql Left Join very slow query

我有2表約3000/4000行。 我需要使用“左連接”建立關系,以通過搜索文本或日期時間來過濾結果。 我還需要計算分頁的總行數。 當我運行查詢時,運行速度極慢,請考慮通過控制台大約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子句。 只是從我的手機打錯了。 現在是正確的,而且非常慢:)

新更新:如果將關系從“左聯接”更改為“右聯接”,它將變得非常快。

從正確的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

您的情況不是很清楚。 如果可以提供良好的數據樣本,我們可以找到更好的查詢。

我猜你不需要bZ 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

對此采取狂妄的嘗試,只是為了向您指出一般方向,以下是對該查詢的可能重寫:( 我不保證它會起作用...)

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. 為了方便起見,用AB標識了這些表。
  3. LEFT JOIN正在USING (id) ,它是WHERE A.id = B.id簡寫。
  4. GROUP BY子句指定將數據按這三個變量分組。 所有這些都必須出現在SELECT子句中,並且出現的所有其他內容必須是聚合函數,例如COUNT()SUM()

同樣, 我不保證該查詢有效。 但它應說明一般應如何構造這樣的查詢。

除非您要從“右側”表中獲取NULLs ,否則不要使用LEFT 在這種情況下,我認為您不這樣做。

( SELECT COUNT... )意味着它需要針對每行進行重新評估,而不必這樣做。 擺脫它; 使用SQL_CALC_FOUND_ROWS

是否正在搜索AX和BZ 相同的子字符串? 它們是否始終具有相同的價值? 如果是這樣,則僅搜索其中之一。 (例如LIKE '%...'是查詢中昂貴的一部分。)

使用JOIN會增加行數; 然后您添加了GROUP BY來縮小它。 這種充氣/放氣是昂貴的。

COUNT(*)無法通過'%mytext%'進行過濾,因此它無法滿足您“ 145行30-39行”的要求。

是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:很多vs很多:很多),因此該解決方案可能是錯誤的。 不正確性將由子查詢返回多行而跳出。

因此,我可能沒有給您“正確”的答案,但是希望我給您足夠的線索,以便您可以更緊密地聯系。

之后,也許可以通過“記住您離開的地方”而不是使用OFFSET來使分頁更快。 我的博客

如果您想進一步討論,請提供SHOW CREATE TABLE ,不要混淆列名-通常,這些名稱會提供您意圖的線索。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM