2013-07-29 56 views
1

我有3個表格。 第一: 「atributy」 二: 「atributy_value」 三: 「導航產品」如何加快MySQL查詢?從3個表格加載數據

我有這個疑問第一:

SELECT a.*, p.ATTRIBUTE_CODE, p.ATTRIBUTE_VALUE, p.KATEGORIA 
FROM atributy a JOIN produkty p ON p.ATTRIBUTE_CODE 
LIKE CONCAT('%', a.code, '%') 
AND 
KATEGORIA IN ('$kategoria_sql') 
GROUP BY a.value 

我的第二個查詢是這樣的:

SELECT * FROM atributy_value 
INNER JOIN produkty 
ON produkty.ATTRIBUTE_VALUE LIKE CONCAT('%', atributy_value.ValueCode, '%') 
AND AttributeCode = '$atribut_kod' 
AND KATEGORIA IN ('$kategoria_sql') 
GROUP BY atributy_value.Value 

幫助我請從這2個查詢的1個更好。 原因是:我的網上商店加載時間過長。

編輯:

$query = mysql_query(" 
SELECT a.*, p.ATTRIBUTE_CODE, p.ATTRIBUTE_VALUE, p.KATEGORIA 
FROM atributy a JOIN produkty p ON p.ATTRIBUTE_CODE LIKE CONCAT('%', a.code, '%') 
AND KATEGORIA IN ('$kategoria_sql') 
GROUP BY a.value "); 

while($result = mysql_fetch_object($query)){ 

$atribut_kod = $result->code; 
$atribut_value = $result->value; 
$nazov_produktu = $result->NAZOV; 
$value1 = $result->ATTRIBUTE_VALUE; 
$value1 = explode(" ", $value1); 

$value1_count = count($value1); 

echo "<div class=\"parametre_panel\"> 
<h3>".$atribut_value."</h3> 
"; 

$url_kody .= "$atribut_kod,"; 

$hodnoty_qry = mysql_query(" 
SELECT * FROM atributy_value 
INNER JOIN produkty ON produkty.ATTRIBUTE_VALUE LIKE CONCAT('%', atributy_value.ValueCode, '%') 
AND AttributeCode = '$atribut_kod' 
AND KATEGORIA IN ('$kategoria_sql') 
GROUP BY atributy_value.Value "); 

while($hodnoty_res = mysql_fetch_object($hodnoty_qry)){ 
$cislo_hodnoty = $hodnoty_res->ValueCode; 
echo "<input type=\"checkbox\" class=\"ZobrazParametrickeVyhladavanie\" name=\"value[]\" id=\"$cislo_hodnoty\" value=\"".$atribut_kod."-".$cislo_hodnoty."\"><label for=\"$cislo_hodnoty\">".$hodnoty_res->Value."</label> 
"; 

$url_hodnoty .= "$cislo_hodnoty,"; 
} //second query while() 
echo "</div>"; 
} //first query while() 

編輯2:

我的表結構

produkty:  http://i.imgur.com/J4Kz2CE.png 
atributy_value: http://i.imgur.com/nX1uRph.png 
atributy:  http://i.imgur.com/mlCa3It.png 

指標:

atributy:   http://i.imgur.com/ppMEEOe.png 
atributy_value: http://i.imgur.com/RHAeSiu.png 
produkty:   http://i.imgur.com/IUrgy9l.png 
+0

你還沒有提供很多信息。你可能有錯誤的索引,查詢可能太複雜,當它不需要時等你的答案不能正確回答,不知道更多的信息。 –

+0

你的while循環完美嗎?我的意思是有沒有錯誤?由於我在動態查詢中看到一個變量名。 – Romesh

+0

是的,這個工程,但很長的加載:( –

回答

0

你可以試試下面的查詢:

SELECT a.*, 
     p.ATTRIBUTE_CODE, 
     p.ATTRIBUTE_VALUE, 
     p.KATEGORIA 
    FROM atributy a 
    JOIN (SELECT * 
      FROM atributy_value 
     INNER JOIN produkty 
      ON produkty.ATTRIBUTE_VALUE LIKE CONCAT('%', atributy_value.ValueCode, '%') 
      AND AttributeCode = '$atribut_kod' 
      AND KATEGORIA IN ('$kategoria_sql') 
     GROUP BY atributy_value.Value) p 
    ON p.ATTRIBUTE_CODE LIKE CONCAT('%', a.code, '%') 
    AND KATEGORIA IN ('$kategoria_sql') 
GROUP BY a.value 

在內部查詢選擇唯一需要的列

希望這個作品。

+0

'$ atribut_kod'在while()第一次查詢中。 –

+0

其中'While()'?你沒有提到過在你的文章中的任何地方循環請提供詳細信息,以便我們可以幫助你 – Romesh

+0

已編輯。全部代碼 –

0

這裏有兩件事情很慢。

第一 - 不必要的外部/內部循環。應該可以在單個SQL查詢中執行此操作,這將節省大量時間。 沒有看到你的表的定義,這是最好的,我可以建議:

SELECT a.*, p.*, av.* 
FROM produkty p 
JOIN atributy a ON p.ATTRIBUTE_CODE LIKE CONCAT('%', a.code, '%') 
JOIN atributy_value av ON p.ATTRIBUTE_VALUE LIKE CONCAT('%', av.ValueCode, '%') 
WHERE 
KATEGORIA IN ('$kategoria_sql') 

至少它是一個出發點進行測試。

第二個 - 使用LIKE'%value%'在兩個表之間進行連接。是否沒有將這兩個錶鏈接在一起的整數ID?或者至少,如果文本是完全匹配的,你可以刪除'%'?

編輯(追加表結構之後):

你有兩個連接,從一個漂亮的索引整數atributy_value.ValueCode到非索引文本字段produkty.ATTRIBUTE_CODE第一,從非索引的文本字段中的第二atributy.code轉換爲另一個非索引文本字段produkty.ATTRIBUTE_CODE。

這不是一個好的表結構,如果每個表都有一個唯一的整數ID加入,它會更容易,更快。但是你可能沒有時間去改變它。

你可以在原始查詢中只刪除%,並堅持列間完全匹配嗎? 爲了簡單起見,你可以只更換:

LIKE CONCAT('%', a.code, '%') 

更換

= a.code 

LIKE CONCAT('%', atributy_value.ValueCode, '%') 

= CONVERT(varchar(500), atributy_value.ValueCode) 

這取代將使它更快。如果還不夠,可以在Produkty.ATTRIBUTE_CODE和Produkty.ATTRIBUTE_VALUE和atributy.code上添加索引。

+0

爲什麼搜索LIKE'%value%'很慢:http:// www.brentozar.com/archive/2010/06/sargable-why-string-is-slow/ –

+0

Muste be like,因爲值大於1.屏幕截圖:http://i.imgur.com/p4EH1gt.png –

+0

在一列中存儲多個值是數據庫中的不良做法......它會導致與此類似的問題。即使向這些文本列添加索引也不會使其更快,因爲索引僅用於查找已知第一個字符的字符串。 我留下的唯一建議是用像我的示例SQL這樣的單個查詢替換外部/內部查詢 - 你試過了嗎? –

0

1)在您的查詢上運行EXPLAIN並在必要時添加索引。恕我直言,這些查詢並不意味着生產運行。不過,我在下面提出了一個建議。

2)讓MySQL爲您處理查詢執行計劃。而不是提到一個JOIN。試試這個

$query = mysql_query(" 
         SELECT a.*, p.ATTRIBUTE_CODE, p.ATTRIBUTE_VALUE, p.KATEGORIA 
         FROM atributy a,produkty p 
         WHERE p.ATTRIBUTE_CODE LIKE CONCAT('%', a.code, '%') 
         AND KATEGORIA IN ('$kategoria_sql') 
         GROUP BY a.value "); 

2)內部查詢也更改爲以下:

SELECT atributy_value.* FROM atributy_value AS atributy_value, produkty AS produkty 
WHERE 
produkty.ATTRIBUTE_VALUE LIKE CONCAT('%', atributy_value.ValueCode, '%') 
AND atributy_value.AttributeCode = '$atribut_kod' 
AND produkty.KATEGORIA IN ('$kategoria_sql') 
GROUP BY atributy_value.Value ") 

我需要對錶結構的更多細節,雖然

3)運行上述的查詢的解釋。如果你有任何缺失的索引,請添加它們

+0

當然你需要指定JOIN來告訴mysql你想要的表之間的關係嗎?否則你只需從表中得到每個組合。 –

+0

編輯後,我添加了我的索引和結構的屏幕截圖 –

+0

@GrahamGriffiths:不,你不需要,MySQL實際上是自己完成的,在上例中SELECT atributy_value。* FROM atributy_value AS atributy_value,產品 WHERE produkty.ATTRIBUTE_VALUE LIKE CONCAT('%',atributy_value.ValueCode,'%')與做INNER JOIN相同。當然,這並不有助於上述示例中的連接使用LIKE (最糟糕的一種),因此,將它從連接中取出可以讓MySQL處理它 –