2013-07-18 23 views
1

我有问题。以下查询需要2 - 3秒钟才能完成,我不知道为什么。我有两个表涉及一个项目列表和另一个与每个项目的属性列表。项目表使用唯一的主键索引,而属性表具有外键约束。使用子选择增加查询的速度?

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

我不知道如何加快查询,并会感谢任何建议。

的数据库为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表连接多个行一行项目表中。

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

:(

+0

你有没有索引?如果是,请分享这些专栏。 – Learner

+0

@学习者我已将该索引添加到帖子中 – TheSnooker

+0

此查询可能会更好地使用'JOIN'编写。 –

回答

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有影响。

+0

该解决方案似乎有助于缩短响应时间。它仍然是约1.3秒,但好于2.9秒:D – TheSnooker

0

的“从属SUBQUERY”是什么在此查询查杀性能它为每一个不同的项目Id在外部查询运行一次子查询它应该是为连接好得多:。

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; 
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; 

这工作如果在对EAC最多一个匹配属性h项目。否则,你需要select distinct(这可能会损害性能,除非你已经在做排序)。

为了方便这个join,创建索引eshop_items_attributes(attType, attValue, attItemId)。该指数应该满足join而没有必须读取表格,其余的是处理结果集。

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