2014-02-13 190 views
1

我运行此查询:为什么这个SQL查询很慢?

SELECT DISTINCT "items"."id" 
FROM "items" 
LEFT OUTER JOIN "item_explicit_mods" ON "item_explicit_mods"."item_id" = "items"."id" 
LEFT OUTER JOIN "explicit_mods" ON "explicit_mods"."id" = "item_explicit_mods"."explicit_mod_id" 
LEFT OUTER JOIN "item_implicit_mods" ON "item_implicit_mods"."item_id" = "items"."id" 
LEFT OUTER JOIN "implicit_mods" ON "implicit_mods"."id" = "item_implicit_mods"."implicit_mod_id" 
LEFT OUTER JOIN "shops" ON "shops"."id" = "items"."shop_id" 
WHERE ((item_explicit_mods.explicit_mod_id = 35 
     AND item_explicit_mods.primary_value >= 5 AND item_explicit_mods.primary_value <= 6) 
    OR (item_explicit_mods.explicit_mod_id = 48)) 
GROUP BY items.id 
HAVING COUNT(item_explicit_mods.id) = 2 
ORDER BY "items"."created_at" 
ASC LIMIT 100 

sqlite的解释是生产这种

0|0|0|SCAN TABLE items USING INTEGER PRIMARY KEY (~1000000 rows) 
0|1|1|SEARCH TABLE item_explicit_mods USING AUTOMATIC COVERING INDEX (explicit_mod_id=?) (~7 rows) 
0|1|1|SEARCH TABLE item_explicit_mods USING AUTOMATIC COVERING INDEX (explicit_mod_id=?) (~7 rows) 
0|2|2|SEARCH TABLE explicit_mods USING INTEGER PRIMARY KEY (rowid=?) (~1 rows) 
0|3|3|SEARCH TABLE item_implicit_mods USING AUTOMATIC COVERING INDEX (item_id=?) (~7 rows) 
0|4|4|SEARCH TABLE implicit_mods USING INTEGER PRIMARY KEY (rowid=?) (~1 rows) 
0|5|5|SEARCH TABLE shops USING INTEGER PRIMARY KEY (rowid=?) (~1 rows) 
0|0|0|USE TEMP B-TREE FOR DISTINCT 
0|0|0|USE TEMP B-TREE FOR ORDER BY 

这个查询花费> 10秒运行。任何想法为什么它正在对主键进行扫描?

+0

为什么你使用'当你已经在同一列分组distinct'? – Luaan

+0

这是ruby on rails activerecord正在生成的查询 –

+0

如果您将'where'条件更改为两个条件中的一个,则需要多长时间?有时候,'或'会导致优化器出现问题。 –

回答

1

尝试查询更改这个

SELECT "items"."id" 
FROM "items" 
INNER JOIN "item_explicit_mods" ON "item_explicit_mods"."item_id" = "items"."id" AND (((item_explicit_mods.explicit_mod_id = 35 
     AND item_explicit_mods.primary_value >= 5 AND item_explicit_mods.primary_value <= 6) 
    OR (item_explicit_mods.explicit_mod_id = 48))) 
LEFT OUTER JOIN "explicit_mods" ON "explicit_mods"."id" = "item_explicit_mods"."explicit_mod_id" 
LEFT OUTER JOIN "item_implicit_mods" ON "item_implicit_mods"."item_id" = "items"."id" 
LEFT OUTER JOIN "implicit_mods" ON "implicit_mods"."id" = "item_implicit_mods"."implicit_mod_id" 
LEFT OUTER JOIN "shops" ON "shops"."id" = "items"."shop_id" 
GROUP BY items.id 
HAVING COUNT(item_explicit_mods.id) = 2 
ORDER BY "items"."created_at" 
ASC LIMIT 100 
+0

就这样做了。查询时间缩短到280ms –

1

任何想法为什么它在主键上执行扫描?

我想是因为你这样做:

SELECT DISTINCT "items"."id" 

该表的列id是主键。您正在寻找引用连接中其他表的不同标识符。出于这个原因,主键上有一个SCAN。

此外,为什么你将的结果分组,而你只是在寻找不同的标识符?