2013-07-29 54 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处理它 –