我在 MySQL 中有一个简单的子查询,它会生成一组代码,例如“LPR”、“LFR”、“LFL”(可以返回更多代码)。 在我的主查询中使用它会减慢速度,就像它可能需要一两分钟才能运行一样。
我无法显示完整的代码,并且
orders
表中有超过 2,000,000 行,但是,它基本上是:
子查询:
(SELECT DISTINCT prefix
FROM `photo`
WHERE thedate BETWEEN '2024/02/10' AND '2024/02/20'
AND user = 'ABCD1')
主要查询:
SELECT
field1,
field2
FROM `orders`
WHERE ((orders.buyers_date) BETWEEN '2024/02/01' AND '2024/02/29') AND orders.user = 'ABCD1'
AND orders.prefix IN(
(SELECT DISTINCT prefix FROM `photo` WHERE thedate BETWEEN '2024/02/10' AND '2024/02/20' AND user = 'ABCD1')
)
如果在 MainQuery 中,我直接用代码替换
IN
,如
SELECT
field1,
field2
WHERE ((buyers_date) BETWEEN '2024/02/01' AND '2024/02/29') AND orders.user = 'ABCD1'
AND orders.prefix IN('LPR','LFR','LFL')
查询大约需要6秒。我认为子查询会先运行,然后是主查询。好像不是这样的。
我确实尝试过:
SET @prefs = (SELECT DISTINCT prefix FROM `photo` WHERE thedate BETWEEN '2024/02/10' AND '2024/02/20' AND user = 'ABCD1')
SELECT @prefs;
结果是“MySQL 返回了一个空结果集(即零行)”,这是在撒谎!
有什么想法吗?
使用存在的地方:
SELECT field1, field2
FROM orders
WHERE orders.buyers_date BETWEEN '2024/02/01' AND '2024/02/29'
AND orders.user = 'ABCD1'
AND EXISTS ( SELECT NULL
FROM photo
WHERE photo.thedate BETWEEN '2024/02/10' AND '2024/02/20'
AND photo.user = 'ABCD1'
AND orders.prefix = photo.prefix
);
PS。您的日期文字格式错误(从 MySQL 的角度来看) - 您使用 VARCHAR 数据类型而不是 DATE 吗?
添加这些索引——这些复合顺序中列的顺序很重要:
photo: INDEX(user, theDate, prefix)
orders: INDEX(user, prefix, buyers_date)
orders: INDEX(prefix, user, buyers_date)
IN ( SELECT ... )
很少是最佳的。
这可能是构建查询的最佳方式:
SELECT o.field1, o.field2
FROM ( SELECT DISTINCT prefix
FROM `photo`
WHERE thedate BETWEEN '2024/02/10' AND '2024/02/20'
AND user = 'ABCD1')
) AS p
JOIN `orders` AS o ON o.prefix = p.prefix
WHERE o.buyers_date BETWEEN '2024/02/01' AND '2024/02/29'
AND orders.user = 'ABCD1'
(我不知道我对
orders
的索引建议中哪一个更好。通过两者兼而有之,优化器将选择它认为更好的一个。选择 may 取决于数据的分布,因此它可能会改变。请参阅 EXPLAIN SELECT...
)
还有,不知道Akina的建议会不会更好。但他的表述需要:
photo: INDEX(user, prefix, theDate)
orders: INDEX(user, buyers_date, prefix)