【发布时间】:2019-12-29 00:51:10
【问题描述】:
我正在使用 MySQL 5.7.18-16。
我使用的表格:
CREATE TABLE `invoice` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`transaction_id` bigint(20) unsigned NOT NULL,
`transaction_name` varchar(50) NOT NULL,
`unit_price` decimal(19,5) DEFAULT NULL,
`quantity` decimal(19,5) DEFAULT NULL,
`customer_name` varchar(50) DEFAULT NULL,
`date` bigint(20) NOT NULL,
PRIMARY KEY (`ID`),
KEY `i_transaction_id` (`transaction_id`),
KEY `i_date` (`date`)
)
CREATE TABLE `transaction` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`transaction_id` bigint(20) unsigned NOT NULL,
....
)
CREATE TABLE `hierarchy` (
`PRODUCT_ID` int(11) unsigned NOT NULL,
`PRODUCT_NAME` varchar(255) NOT NULL,
`PRODUCT_FAMILY_ID` int(11) unsigned NOT NULL,
`PRODUCT_FAMILY_NAME` varchar(255) NOT NULL,
`ORG_ID` int(11) unsigned NOT NULL,
`ORG_NAME` varchar(255) NOT NULL
...
)
CREATE TABLE `product` (
`ID` int(11) unsigned NOT NULL AUTO_INCREMENT,
`PRODUCT_NAME` varchar(50) NOT NULL,
`COMPONENT_NAME` varchar(50) NOT NULL,
...
)
每条发票记录都与交易和客户名称相关,每笔交易都与产品和组件相关。每个产品都属于一个产品系列,每个产品系列都属于一个组织。
我的要求:
我需要根据指定的发票日期计算不同层级(组织/产品系列/产品/组件)下每个客户名称的成本和数量,并按每个客户名称的成本排序。
我当前查询每个组织下每个客户的成本/数量:
SELECT
h.org_id,
h.org_name,
h.product_family_id,
h.product_family_name,
h.product_id,
h.product_name,
p.component_id,
p.component_name,
i.transaction_id,
i.customer_name,
sum(CASE WHEN i.transaction_name = 'TEST' THEN i.quantity END) AS records,
sum(i.unit_price * i.quantity) AS cost
FROM invoice i
LEFT JOIN transaction t
ON i.transaction_id = t.transaction_id
JOIN hierarchy h
ON t.product_id = h.product_id
JOIN product p
ON t.product_id = p.id
WHERE i.date >= 1514764800000
AND i.date <= 1543622400000
GROUP BY h.org_id, i.customer_name
ORDER by i.cost DESC;
对于其他级别的计算,我只是更改了 WHERE 和 GROUP BY:
//By product_family under one specific org
WHERE h.org_id = 9
AND i.date >= 1514764800000
AND i.date <= 1543622400000
GROUP BY h.product_family_id, i.customer_name
ORDER by i.cost DESC;
//By product under one specific product family
WHERE h.product_family_id = 2011
AND i.date >= 1514764800000
AND i.date <= 1543622400000
GROUP BY h.product_id, i.customer_name
ORDER by i.cost DESC;
//By component under one specific product
WHERE h.product_id = 101
AND i.date >= 1514764800000
AND i.date <= 1543622400000
GROUP BY p.component_name, i.customer_name
ORDER by i.cost DESC;
组织级计算在生产数据库上运行大约需要 3.5 秒,这太慢了。一个主要原因是“发票”表无法使用任何索引。 (我为'i.date'创建了索引,但由于日期范围太大,没有使用索引。)
是否有任何可能的方法来重写此查询以优化速度?
【问题讨论】:
-
您能否更新问题以包括数据库(我假设是 MySQL)和正在使用的版本?
-
您在
SELECT中包含了一堆不在GROUP BY中的列。这是一个格式错误的查询。 -
我已经更新了我使用的 MySQL 版本。我知道我应该在 GROUP BY 中包含 SELECT 中的所有列,但这无助于提高性能,这是我现在想要改进的主要内容;(
-
这些日期以人类可读的形式是什么? WHERE i.date >= 1514764800000 AND i.date
标签: mysql sql performance query-optimization sql-optimization