Mysql 子查询 运行 在实时服务器上速度慢但在本地速度快
Mysql subquery run slow on live server but fast on local
我有一个非常简单的查询,在我的本地 windows 机器上需要 0.04 秒,但在我们的实时服务器上 linux 机器需要 30 秒!
有人熟悉同样的问题吗?
这是查询:
SELECT DISTINCT
s.carId FROM
cardetail_search s WHERE
s.carId IN (SELECT DISTINCT c.carId FROM carid id JOIN car c ON c.carId = id.carId WHERE id.ProductNumber = 'pnumber' OR id.ProductNumber = 'pnumber2')
AND pictureTableId IN (SELECT DISTINCT pictureTableId FROM cardetail WHERE ProductNumber = 'pnumber' OR ProductNumber = 'pnumber2')
编辑:任何子查询运行缓慢
解决方案:当我使用 INNER JOIN 时,而不是使用 COLUMN IN() 的子查询,它按预期工作。检查重构查询的批准答案。
造成这种差异的一个可能原因是您有不同的缓存子查询配置,并且 mysql 在 linux 服务器的磁盘上创建临时 tables。
这个过程需要很长时间,而且效率不高。在 mysql 决定在磁盘中创建临时 table 之前,您可以通过修改内存上临时 table 的最大大小来增加分配的内存量:
查看这 2 个变量的配置并考虑增加它们。
- tmp_table_size
- max_heap_table_size
根据评论,我认为 dbs 上的 "statistics" 是不同的。
你可以试试这个,看看你是否获得更好的性能(数据库引擎可以在使用 INNER JOIN 与 COLUMN IN (...) 时准备不同的计划:
SELECT DISTINCT
s.carId
FROM cardetail_search s
INNER JOIN (SELECT DISTINCT c.carId FROM carid id
INNER JOIN car c ON c.carId = id.carId
WHERE id.ProductNumber = 'pnumber' OR id.ProductNumber = 'pnumber2') X ON s.carID = X.carID
INNER JOIN (SELECT DISTINCT pictureTableId FROM cardetail WHERE ProductNumber = 'pnumber' OR ProductNumber = 'pnumber2') Y ON s.pictureTableId = Y.pictureTableId
似乎没有必要提及 car
?
SELECT DISTINCT carId
FROM cardetail_search AS s
JOIN carid AS cid ON s.carId = cid.carId
JOIN cardetail AS cd ON s.pictureTableId = cd.pictureTableId
WHERE cid.ProductNumber IN (...)
AND cd.ProductNumber IN (...)
或者,您可能希望 ProductNumber 匹配...
SELECT DISTINCT carId
FROM cardetail_search AS s
JOIN carid AS cid ON s.carId = cid.carId
JOIN cardetail AS cd ON s.pictureTableId = cd.pictureTableId
WHERE cid.ProductNumber IN (...)
AND cd.ProductNumber = cid.ProductNumber
不要增加 tmp_table_size
超过 RAM 的大约 1%。否则在极端情况下您可能会耗尽 RAM。
IN ( SELECT ... )
过去效率极低。
FROM ( SELECT ... ) JOIN ( SELECT ... )
目前效率低下,因为两个子查询都没有任何索引。
我有一个非常简单的查询,在我的本地 windows 机器上需要 0.04 秒,但在我们的实时服务器上 linux 机器需要 30 秒!
有人熟悉同样的问题吗?
这是查询:
SELECT DISTINCT
s.carId FROM
cardetail_search s WHERE
s.carId IN (SELECT DISTINCT c.carId FROM carid id JOIN car c ON c.carId = id.carId WHERE id.ProductNumber = 'pnumber' OR id.ProductNumber = 'pnumber2')
AND pictureTableId IN (SELECT DISTINCT pictureTableId FROM cardetail WHERE ProductNumber = 'pnumber' OR ProductNumber = 'pnumber2')
编辑:任何子查询运行缓慢
解决方案:当我使用 INNER JOIN 时,而不是使用 COLUMN IN() 的子查询,它按预期工作。检查重构查询的批准答案。
造成这种差异的一个可能原因是您有不同的缓存子查询配置,并且 mysql 在 linux 服务器的磁盘上创建临时 tables。 这个过程需要很长时间,而且效率不高。在 mysql 决定在磁盘中创建临时 table 之前,您可以通过修改内存上临时 table 的最大大小来增加分配的内存量:
查看这 2 个变量的配置并考虑增加它们。
- tmp_table_size
- max_heap_table_size
根据评论,我认为 dbs 上的 "statistics" 是不同的。 你可以试试这个,看看你是否获得更好的性能(数据库引擎可以在使用 INNER JOIN 与 COLUMN IN (...) 时准备不同的计划:
SELECT DISTINCT
s.carId
FROM cardetail_search s
INNER JOIN (SELECT DISTINCT c.carId FROM carid id
INNER JOIN car c ON c.carId = id.carId
WHERE id.ProductNumber = 'pnumber' OR id.ProductNumber = 'pnumber2') X ON s.carID = X.carID
INNER JOIN (SELECT DISTINCT pictureTableId FROM cardetail WHERE ProductNumber = 'pnumber' OR ProductNumber = 'pnumber2') Y ON s.pictureTableId = Y.pictureTableId
似乎没有必要提及 car
?
SELECT DISTINCT carId
FROM cardetail_search AS s
JOIN carid AS cid ON s.carId = cid.carId
JOIN cardetail AS cd ON s.pictureTableId = cd.pictureTableId
WHERE cid.ProductNumber IN (...)
AND cd.ProductNumber IN (...)
或者,您可能希望 ProductNumber 匹配...
SELECT DISTINCT carId
FROM cardetail_search AS s
JOIN carid AS cid ON s.carId = cid.carId
JOIN cardetail AS cd ON s.pictureTableId = cd.pictureTableId
WHERE cid.ProductNumber IN (...)
AND cd.ProductNumber = cid.ProductNumber
不要增加 tmp_table_size
超过 RAM 的大约 1%。否则在极端情况下您可能会耗尽 RAM。
IN ( SELECT ... )
过去效率极低。
FROM ( SELECT ... ) JOIN ( SELECT ... )
目前效率低下,因为两个子查询都没有任何索引。