Mysql JOIN vs UNION vs IN()-大表和许多WHERE条件
我使用MySQL 5.5,创建了3个表用于测试:Mysql JOIN vs UNION vs IN()-大表和许多WHERE条件,mysql,sql,Mysql,Sql,我使用MySQL 5.5,创建了3个表用于测试: 属性(实体id、cid、aid、值)-索引:全部 项目(实体id、价格、货币)-索引:实体id 汇率(货币从、货币到、汇率)-指数:无 我需要计算指定条件(按属性搜索)的结果,并选择按某列排序的X行。 查询应支持在项目属性(属性表)中搜索。 首先我有一个这样的问题: SELECT i.entity_id, i.price * COALESCE(r.rate, 1) AS final_price FROM items i JOIN attribu
SELECT i.entity_id, i.price * COALESCE(r.rate, 1) AS final_price
FROM items i
JOIN attributes a ON a.entity_id = i.entity_id
LEFT JOIN rates r ON i.currency = r.currency_from AND r.currency_to = 'EUR'
WHERE a.cid = 4 AND ( (a.aid >= 10 AND a.value > 2000) OR (a.aid <= 10 AND a.value > 5) )
HAVING final_price BETWEEN 0 AND 9000
ORDER BY final_price DESC
LIMIT 20
我将COUNT()分组为7(要搜索的属性数),因为我需要查找具有所有这些属性的项目
解释基本查询(第一个查询):
我读了很多关于比较UNION
vsJOIN
vsIN()
的主题,最好的结果是第二个选项,但总是太慢
有没有办法在这里获得更好的性能?为什么这么慢?
我是否应该考虑将一些逻辑(将此查询拆分为3个小查询)移动到后端(php/ror)代码中?我会稍微重新构造您的查询,并首先创建属性表 然后加入到项目中。另外,我会在上有一个覆盖指数 items表通过(实体id、价格)和属性表上的索引 打开(cid、aid、value、entity_id)和您的费率表索引 ON(货币从、货币到、汇率)。这样,所有的索引都覆盖了索引 引擎不需要转到原始数据页来获取数据,它可以 从已用于加入/标准的索引中提取
SELECT
i.entity_id,
i.price * COALESCE(r.rate, 1) AS final_price
FROM
attributes a
JOIN items i
ON a.entity_id = i.entity_id
LEFT JOIN rates r
ON i.currency = r.currency_from
AND r.currency_to = 'EUR'
WHERE
a.cid = 4 AND ( (a.aid >= 10 AND a.value > 2000) OR (a.aid <= 10 AND a.value > 5) )
HAVING
final_price BETWEEN 0 AND 9000
ORDER BY
final_price DESC
LIMIT 20
您似乎没有用于
join
s的列的索引。这就是从优化开始的地方。但是如果你有一个生成大量查询的整个系统,这个问题对于这样的论坛来说可能太大了。我为currency和currency\u添加了索引到/currency\u from,现在是~1.3535。我只有搜索查询。现在需要~0.21。我在问题中添加了更多的条件,请看。@dem,修改后的答案。你的意思是在旧的where语句之外添加额外的in()语句以获得帮助吗?@dem,是的。这样,如果“aid”值为3,它将使(…,…,…,…,…,…)中的“and.id”失败,并且永远不必使用所有的and/or cast值和/或cast值等进入其余部分。。。它马上就失败了,并且不需要满足其余的条件。我要求确认,因为它不会改变执行时间。也许,我会在更大的布景上看到不同,对吗?顺便问一下,为了证明你的话,你知道一些关于解析SQL查询(MySQL)的材料吗?
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE a ALL entity_id,value NULL NULL NULL 379999 Using where; Using temporary; Using filesort
1 SIMPLE i eq_ref PRIMARY PRIMARY 4 testowa.a.entity_id 1 Using where
1 SIMPLE r ALL NULL NULL NULL NULL 2
SELECT
i.entity_id,
i.price * COALESCE(r.rate, 1) AS final_price
FROM
attributes a
JOIN items i
ON a.entity_id = i.entity_id
LEFT JOIN rates r
ON i.currency = r.currency_from
AND r.currency_to = 'EUR'
WHERE
a.cid = 4 AND ( (a.aid >= 10 AND a.value > 2000) OR (a.aid <= 10 AND a.value > 5) )
HAVING
final_price BETWEEN 0 AND 9000
ORDER BY
final_price DESC
LIMIT 20
a.cid = 4
AND a.id in ( 10, 121, 45, 95, 98, 199, 102 )
AND ( rest of the complex aid, casting and between criteria )