1

I'm have a question. The following query is taking upwards of 2 - 3 seconds to exicute and I'm not sure why. I have 2 tables involved one with a list of items and the another with a list of attribute's for each item. The items table is indexed with unique primary key and the attributes table has a foreign key constraint.

The relationship between the items table is ONE TO MANY to the attributes.

I am not sure how else to speed up query and would appreciate any advice.

The database is 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

Index: eshop_items_attributes

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

Index: eshop_items

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

Can't use a join because the item_attributes table is a key -> value pair table. So for every record in the items_attributes table there can be many item id's

here is a sample

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

So a join wouldn't work because I can't join multiple rows from the items_attributes table to one row in the items table.

I can't write a query where attribute_index is = to 2 AN attribute_index = 10. I would always get back no results.

:(

4

3 回答 3

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 

通过将 btree 更改为 eshop_items_attributes 上的位图,您将看到进一步的收获。但请注意:位图对 INSERT/UPDATE 有影响。

于 2013-07-19T00:10:16.123 回答
0

“DEPENDENT SUBQUERY”是这个查询中扼杀性能的原因。它必须为外部查询中的每个不同的 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;
于 2013-07-18T21:12:38.967 回答
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 而不必读表,剩下的就是处理结果集。

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

于 2013-07-18T21:14:01.890 回答