我是MySQL的新手。所以我发现有人在我们的生产环境中写了一些SQL:
SELECT o.`erp_orders_id`
FROM `erp_orders` o
WHERE o.`orders_status`> 2
AND o.`orders_status`< 5
AND o.`shipmentAutoMatched` IN
(SELECT s.`shipmentID`
FROM `erp_shipment` s
WHERE s.`shipmentScanLocal` = 2)
其中s.shipmentID
为int(11)
而o.shipmentAutoMatched
为int(6)
此查询命中索引
IDX_OR_OR_CU(orders_status, orders_type, currency_type)
虽然我实际上有另一个索引:
IDX_OR_SH(orders_status, shipmentAutoMatched)
我认为可能更有效率。如果我将IN
指令更改为数字:
IN(10, 11, 12)
IDX_OR_SH
被正确命中。所以我认为唯一的问题可能是int(11)
和int(6)
。
所以问题:
int(11)
和int(6)
都是int
并且它们实际上都存储为INT32
答案 0 :(得分:1)
对于每个关心这个问题的人来说,这可能是10年前InnoDB的a bug。它应该在MySQL 6.0中得到修复。不幸的是我还在使用5.5。
它与int(11)和int(6)无关。简单地说,所有子查询结果都不会达到父查询的索引。有些人说改为JOIN
声明可以解决这个问题,但它似乎对我不起作用。
当我得到新的东西时,我会回来并更新答案。
答案 1 :(得分:0)
您正在使用子查询的索引,但在将其传递给In
后将其丢失将此查询重写为联接,您将看到速度提升。特别是在旧版本的mysql上(较新的版本具有更好的子查询。)
Mysql非常擅长知道要使用哪个索引。如果它确定一个是比另一个更好的索引。 Mysql通常是正确的。您可以使用FORCE INDEX进行测试。确保你在较小的数据集和较大的数据集上使用它来获得真实的图片
答案 2 :(得分:0)
使用jOIN重写您的查询
SELECT o.`erp_orders_id`
FROM `erp_orders` o
INNER JOIN `erp_shipment` s ON (s.`shipmentID` = o.`shipmentAutoMatched` AND s.`shipmentScanLocal` = 2)
WHERE o.`orders_status`> 2
AND o.`orders_status`< 5
答案 3 :(得分:0)
我认为问题出在int(11)
和int(6)
INT(*)
中的*与空间要求或任何其他性能问题无关,它是&#39;只是 显示宽度 。实际上,使用UNSIGNED ZEROFILL
选项会更有用。例如
INT(6) UNSIGNED ZEROFILL
000001
000011
------
INT(6)
1
11
所以我猜问题应该在其他地方