使用子选择提高查询的速度?

时间:2013-07-18 21:02:41

标签: mysql sql entity-attribute-value

我有一个问题。以下查询需要花费2到3秒才能完成,我不知道为什么。我有2个表涉及一个项目列表,另一个表格包含每个项目的属性列表。 items表使用唯一主键索引,属性表具有外键约束。

项目表之间的关系是属性的一对多。

我不确定如何加快查询速度,并感谢任何建议。

数据库是MYSQL inodb

EXPLAIN SELECT * FROM eshop_items AS ite WHERE (SELECT attValue FROM eshop_items_attributes WHERE attItemId=ite.ItemId ANd attType=5 AND attValue='20')='20' ORDER BY itemAdded DESC LIMIT 0, 18;

id | select_type        | table                  | type | possible_keys | key       | key_len | ref                    | rows  | Extra
1   PRIMARY               ite                       ALL         NULL        NULL        NULL    NULL                     57179   Using where; Using   filesort
2   DEPENDENT SUBQUERY  eshop_items_attributes      ref     attItemId       attItemId    9      gabriel_new.ite.itemId      5    Using where

索引:eshop_items_attributes

Name        Fieldnames  Index Type  Index method
attItemId   attItemId   Normal      BTREE
attType     attType     Normal      BTREE
attValue    attValue    Normal      BTREE

索引:eshop_items

Name            Fieldnames      Index Type  Index method
itemCode        itemCode        Unique      BTREE
itemCodeOrig    itemCodeOrig    Unique      BTREE
itemConfig      itemConfig      Normal      BTREE
itemStatus      itemStatus      Normal      BTREE

无法使用连接,因为item_attributes表是一个键 - >价值对表。因此,对于items_attributes表中的每条记录,可以有许多项目ID

这是一个示例

item_id    attribute_index   attribute_value
12345      10                true
12345      2                 somevalue
12345      6                 some other value
32456      10                true
32456      11                another value
32456      2                 somevalue

因此,连接不起作用,因为我无法将items_attributes表中的多行连接到items表中的一行。

我无法写一个查询,其中attribute_index = = 2 AN attribute_index = 10.我总是得不到任何结果。

:(

3 个答案:

答案 0 :(得分:1)

将查询从关联更改为IN,看看会发生什么。

SELECT * 
  FROM eshop_items AS ite 
 WHERE ItemId IN (
       SELECT attItemId
         FROM eshop_items_attributes 
        WHERE attType=5 
          AND attValue='20')
 ORDER BY itemAdded DESC 
 LIMIT 0, 18 

您可以通过在eshop_items_attributes上将btree更改为位图来获得更多收益。但要注意:位图会对INSERT / UPDATE产生影响。

答案 1 :(得分:0)

“依赖子信息”是此查询中的杀戮性能。它必须为外部查询中的每个不同的ItemId运行子查询一次。作为一个连接应该好多了:

SELECT ite.* FROM eshop_items AS ite 
INNER JOIN eshop_items_attributes AS a ON ite.ItemId = a.attItemId
WHERE a.attType = 5 AND a.attValue = 20
ORDER BY ite.itemAdded DESC LIMIT 0, 18;

答案 2 :(得分:0)

我发现将此类查询视为join

更容易
SELECT ite.*
FROM eshop_items ite join
     eshop_items_attributes ia
     on ia.attItemId = ite.ItemId and
        ia.attType = 5 and
        ia.attValue='20'
ORDER BY ite.itemAdded DESC
LIMIT 0, 18;

如果每个项目最多只有一个匹配属性,则此方法有效。否则,您需要select distinct(这可能会影响性能,除非您已经进行了排序)。

为方便join,请创建索引eshop_items_attributes(attType, attValue, attItemId)。索引应满足join 必须读取表,其余的则处理结果集。

相同的索引可能有助于相关子查询。