MySQL 子查询似乎减慢了我的主查询速度,有关于如何加快速度的提示吗?

问题描述 投票:0回答:2

我在 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 返回了一个空结果集(即零行)”,这是在撒谎!

有什么想法吗?

mysql performance subquery query-optimization
2个回答
1
投票

使用存在的地方:

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 吗?


0
投票

添加这些索引——这些复合顺序中列的顺序很重要:

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)
© www.soinside.com 2019 - 2024. All rights reserved.