我正在研究像这样的表结构(emp_data)
id dept_id emp_id emp_name role
1 101 1001 Tom Good Worker
2 101 1002 Dick Smart Worker
3 102 1001 Harry Hard Worker
4 103 1001 Kate Nice Worker
5 101 1003 Lucy Great Worker
现在,我需要对(dept_id,emp_id)上的组合进行一些非常大的搜索。
我使用tuple搜索,就像这样。
select * from emp_data
where (dept_id, emp_id) in
((101, 1001),
(101, 1002),
(103, 1001));
当表格很长时,这需要相当长的时间。
但如果我这样做,
select * from emp_data
where dept_id in (101, 103)
and (dept_id, emp_id) in
((101, 1001),
(101, 1002),
(103, 1001));
它快得多,甚至100倍。
我不明白的是,
--- ---编辑
我对我桌子上的两个查询做了解释。
那么,在in子句中使用索引列是不是很糟糕?
答案 0 :(得分:1)
根据this question,对MySQL中的元组的支持没有得到优化。正如@ O.Jones在他的评论中写道,MySQL中的查询计划程序是一个非常复杂的野兽,而应该工作的东西并不总是像你期望的那样。
我相信你的第二个查询更快,因为第一个where子句dept_id in (101, 103)
减少了使用元组的第二个搜索空间。查询优化器应该自动执行此操作,但至少在您的示例中不会这样做。
我不相信IN
子句是问题 - 这是一个元组比较,它扫描整个表而不使用可用的索引。
答案 1 :(得分:0)
您的第一个查询基本上是OR
操作。它需要查看您正在检索的每个不同元组的表。所以它会多次重复搜索,也可能会让MySQL查询规划器陷入进行全表扫描的困境。在这种情况下,它为每个元组做一个。这会产生非常糟糕的表现。
在第二个查询中,第一个子句看起来会缩小搜索范围,然后使用索引。
在排除此类问题时,您需要使用EXPLAIN
功能。
如果您按照此类要求投入生产,则可能需要花时间进行以下一对查询。
CREATE TEMPORARY TABLE IF NOT EXISTS searchterms AS
SELECT 101 dept_id, 1001 emp_id
UNION ALL
SELECT 101 dept_id, 1002 emp_id
UNION ALL
SELECT 103 dept_id, 1001 emp_id;
SELECT *
FROM emp_data
JOIN searchterms ON emp_data.dept_id = searchterms.dept_id
AND emp_data.emp_id = searchterms.emp_id;
第一个查询将您的元组放入临时表,第二个在JOIN
操作中使用该表。它可能会更好地进行优化。但你应该尝试一下。编写程序时会有轻微的痛苦,因此它会创建临时表,但这种方法比IN ()
子句更好地扩展。
答案 2 :(得分:0)
出于性能目的,最好不要使用 IN 。
SELECT *
FROM emp_data
WHERE (dept_id = 101 AND emp_id = 1001)
OR (dept_id = 101 AND emp_id = 1002)
OR (dept_id = 103 AND emp_id = 1001)
您可以在每个请求之前使用 EXPLAIN 来检查它们的行为方式(实际上,在大多数情况下,索引不会用于IN语句)。