MySQL 计算字段在 SELECT 子句中重用
MySQL calculated fields reuse in SELECT clause
您将如何完成此任务以获得最佳表现?
Table 架构:
CREATE TABLE `test_truck_report` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`truck_id` INT(11) NOT NULL,
`odometer_initial` INT(11) NOT NULL,
`odometer_final` INT(11) NOT NULL,
`fuel_initial` INT(11) NOT NULL,
`fuel_final` INT(11) NOT NULL,
PRIMARY KEY (`id`)
)
ENGINE=InnoDB;
我要执行的是这个查询:
SELECT
truck_id,
(odometer_final - odometer_initial) AS mileage,
(fuel_initial - fuel_final) AS consumed_fuel,
(consumed_fuel / mileage) AS consumption_per_km
FROM
test_truck_report
WHERE
consumption_per_km > 2
这个乍一看很明显的逻辑不起作用,我不得不改用这个查询:
SELECT
truck_id,
(odometer_final - odometer_initial) AS mileage,
(fuel_initial - fuel_final) AS consumed_fuel,
((fuel_initial - fuel_final) / (odometer_final - odometer_initial)) AS consumption_per_km
FROM
test_truck_report
WHERE
((fuel_initial - fuel_final) / (odometer_final - odometer_initial)) > 2
我假设每次需要放置每个计算字段时不断重新计算它会导致性能显着下降。这只是一个测试用例,实际工作 table 有 50 多个字段,一些计算字段由 10 多个操作数组成。所以目前这是一个非常大的问题。
我不想实际创建这些字段并执行类似操作的原因:
UPDATE
`test_truck_report`
SET
consumed_fuel = fuel_initial - fuel_final
是用户不断更新现有记录,在这种情况下,我需要不断更新该数据。
那么你认为创建实际字段是一个更好的主意吗?或者有什么更好的方法吗?
谢谢。
尝试使用视图:
我们需要一个辅助视图:
CREATE OR REPLACE VIEW vw_truck_data AS
SELECT truck_id,
(odometer_final - odometer_initial) AS mileage,
(fuel_initial - fuel_final) AS consumed_fuel
FROM test_truck_report;
最终观点:
CREATE OR REPLACE VIEW vw_truck_consumption AS
SELECT data.*,
(data.consumed_fuel / data.mileage) AS consumption_per_km
FROM vw_truck_data data;
现在您可以随时以简单易读的方式进行查询:
SELECT *
FROM vw_truck_consumption
WHERE consumption_per_km > 2
这样 MySQL 应该只能将每个字段减去一次,因此性能至少应该与您的解决方案一样好或更好。通常,添加字段的 CPU 成本小于从数据库检索数据的成本,但这当然取决于您的硬件、mysql 版本、配置和数据分布。如果确实是个问题,请进行一些测量。
无论如何请记住,您正在通过 consumption_per_km 进行查询过滤,这是字段的一个功能。由于 MySQL 似乎 lack funtional indexes 它肯定会扫描完整的 table 并且速度很慢。
您将如何完成此任务以获得最佳表现?
Table 架构:
CREATE TABLE `test_truck_report` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`truck_id` INT(11) NOT NULL,
`odometer_initial` INT(11) NOT NULL,
`odometer_final` INT(11) NOT NULL,
`fuel_initial` INT(11) NOT NULL,
`fuel_final` INT(11) NOT NULL,
PRIMARY KEY (`id`)
)
ENGINE=InnoDB;
我要执行的是这个查询:
SELECT
truck_id,
(odometer_final - odometer_initial) AS mileage,
(fuel_initial - fuel_final) AS consumed_fuel,
(consumed_fuel / mileage) AS consumption_per_km
FROM
test_truck_report
WHERE
consumption_per_km > 2
这个乍一看很明显的逻辑不起作用,我不得不改用这个查询:
SELECT
truck_id,
(odometer_final - odometer_initial) AS mileage,
(fuel_initial - fuel_final) AS consumed_fuel,
((fuel_initial - fuel_final) / (odometer_final - odometer_initial)) AS consumption_per_km
FROM
test_truck_report
WHERE
((fuel_initial - fuel_final) / (odometer_final - odometer_initial)) > 2
我假设每次需要放置每个计算字段时不断重新计算它会导致性能显着下降。这只是一个测试用例,实际工作 table 有 50 多个字段,一些计算字段由 10 多个操作数组成。所以目前这是一个非常大的问题。
我不想实际创建这些字段并执行类似操作的原因:
UPDATE
`test_truck_report`
SET
consumed_fuel = fuel_initial - fuel_final
是用户不断更新现有记录,在这种情况下,我需要不断更新该数据。 那么你认为创建实际字段是一个更好的主意吗?或者有什么更好的方法吗?
谢谢。
尝试使用视图:
我们需要一个辅助视图:
CREATE OR REPLACE VIEW vw_truck_data AS
SELECT truck_id,
(odometer_final - odometer_initial) AS mileage,
(fuel_initial - fuel_final) AS consumed_fuel
FROM test_truck_report;
最终观点:
CREATE OR REPLACE VIEW vw_truck_consumption AS
SELECT data.*,
(data.consumed_fuel / data.mileage) AS consumption_per_km
FROM vw_truck_data data;
现在您可以随时以简单易读的方式进行查询:
SELECT *
FROM vw_truck_consumption
WHERE consumption_per_km > 2
这样 MySQL 应该只能将每个字段减去一次,因此性能至少应该与您的解决方案一样好或更好。通常,添加字段的 CPU 成本小于从数据库检索数据的成本,但这当然取决于您的硬件、mysql 版本、配置和数据分布。如果确实是个问题,请进行一些测量。
无论如何请记住,您正在通过 consumption_per_km 进行查询过滤,这是字段的一个功能。由于 MySQL 似乎 lack funtional indexes 它肯定会扫描完整的 table 并且速度很慢。