MySQL 自连接 Table Next/Prev 行性能
MySQL Self Join Table Next/Prev Row Performance
我有一个 table,其中有一列 Sequence
为 table 提供排序。我试图根据 Sequence
将下一行和上一行连接在一起,这样我就可以获得上一个和下一个 SKU 值。
table定义如下:
CREATE TABLE `Builder` (
`Shipment Number` VARCHAR(50) NULL DEFAULT NULL,
`SKU` VARCHAR(50) NULL DEFAULT NULL,
`Pallet Number` VARCHAR(50) NULL DEFAULT NULL,
`Sequence` INT NULL DEFAULT NULL,
INDEX `Primary Index` (`Shipment Number`, `Pallet Number`, `Sequence`) USING BTREE
)
我的查询目前看起来像这样计算下一行 SKU 值:
SELECT
B1.`SKU`,
B1.`Shipment Number`,
B1.`Pallet Number`,
B1.`Sequence`,
B2.`SKU`
FROM Builder B1
LEFT JOIN Builder B2 ON
B2.`Sequence.` = (
SELECT MIN(B3.`Sequence.`)
FROM Builder B3
WHERE
B3.`Sequence` > B1.`Sequence` AND
B3.`Shipment Number` = B1.`Shipment Number` AND
B3.`Pallet Number` = B1.`Pallet Number`
) AND
B1.`Shipment Number` = B2.`Shipment Number` AND
B1.`Pallet Number` = B2.`Pallet Number`
我已经为 (Sequence, Shipment Number, Pallet Number)
添加了一个索引到 Builder
table。
查询正确计算了下一个 SKU,但性能非常糟糕,即使 运行 在我的完整数据集(50,000 行)的一个子集上也需要几分钟。我不确定是否还有其他方法可以提高此查询性能。
运行 在 MySQL 8.0.20.
谢谢!
使用 LEAD()
和 LAG()
而不是联接。它们就是为此而生。
例如:
select
*,
lag(`SKU`) over(partition by `Shipment Number`, `Pallet Number`
order by `Sequence`) as prev_sku,
lead(`SKU`) over(partition by `Shipment Number`, `Pallet Number`
order by `Sequence`) as next_sku
from builder
LAG()
returns前一行的值,根据指定的条件(partition和ordering), 而 LEAD()
returns 根据指定条件的下一行的值。
您还可以添加一个可选的第二个参数(默认为 1
的整数)以指示您想要查看多远(行)。
我有一个 table,其中有一列 Sequence
为 table 提供排序。我试图根据 Sequence
将下一行和上一行连接在一起,这样我就可以获得上一个和下一个 SKU 值。
table定义如下:
CREATE TABLE `Builder` (
`Shipment Number` VARCHAR(50) NULL DEFAULT NULL,
`SKU` VARCHAR(50) NULL DEFAULT NULL,
`Pallet Number` VARCHAR(50) NULL DEFAULT NULL,
`Sequence` INT NULL DEFAULT NULL,
INDEX `Primary Index` (`Shipment Number`, `Pallet Number`, `Sequence`) USING BTREE
)
我的查询目前看起来像这样计算下一行 SKU 值:
SELECT
B1.`SKU`,
B1.`Shipment Number`,
B1.`Pallet Number`,
B1.`Sequence`,
B2.`SKU`
FROM Builder B1
LEFT JOIN Builder B2 ON
B2.`Sequence.` = (
SELECT MIN(B3.`Sequence.`)
FROM Builder B3
WHERE
B3.`Sequence` > B1.`Sequence` AND
B3.`Shipment Number` = B1.`Shipment Number` AND
B3.`Pallet Number` = B1.`Pallet Number`
) AND
B1.`Shipment Number` = B2.`Shipment Number` AND
B1.`Pallet Number` = B2.`Pallet Number`
我已经为 (Sequence, Shipment Number, Pallet Number)
添加了一个索引到 Builder
table。
查询正确计算了下一个 SKU,但性能非常糟糕,即使 运行 在我的完整数据集(50,000 行)的一个子集上也需要几分钟。我不确定是否还有其他方法可以提高此查询性能。
运行 在 MySQL 8.0.20.
谢谢!
使用 LEAD()
和 LAG()
而不是联接。它们就是为此而生。
例如:
select
*,
lag(`SKU`) over(partition by `Shipment Number`, `Pallet Number`
order by `Sequence`) as prev_sku,
lead(`SKU`) over(partition by `Shipment Number`, `Pallet Number`
order by `Sequence`) as next_sku
from builder
LAG()
returns前一行的值,根据指定的条件(partition和ordering), 而 LEAD()
returns 根据指定条件的下一行的值。
您还可以添加一个可选的第二个参数(默认为 1
的整数)以指示您想要查看多远(行)。