[英]How to speed up query in MySQL over 2 tables
I running a very simple query that takes more than 60 seconds.我运行了一个非常简单的查询,耗时超过 60 秒。 Is there a way to speed up the query?有没有办法加快查询速度?
SELECT
AVG(salary.salary_amount),
invoice.invoiced_date
FROM sample_staff.salary
INNER JOIN sample_staff.invoice ON 1=1
AND salary.employee_id = invoice.employee_id
AND invoice.invoiced_date BETWEEN salary.from_date AND salary.to_date
;
Each individual query runs OK:每个单独的查询运行正常:
SELECT
COUNT(salary.salary_amount)
FROM sample_staff.salary
; -- 2,844,047 records in 2.25 seconds
SELECT
COUNT(invoice.invoiced_date)
FROM sample_staff.invoice
; -- 973,488 records in 1.156 seconds
The structures of the table are:表的结构如下:
CREATE TABLE `salary` (
id` int unsigned NOT NULL AUTO_INCREMENT,
employee_id` int unsigned NOT NULL DEFAULT '0',
`salary_amount` decimal(11,2) NOT NULL DEFAULT '0.00',
`from_date` date DEFAULT NULL,
`to_date` date DEFAULT NULL,
`insert_dt` datetime NOT NULL,
`insert_user_id` int NOT NULL DEFAULT '-1',
`insert_process_code` varchar(255) DEFAULT NULL,
`update_dt` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`update_user_id` int NOT NULL DEFAULT '-1',
`update_process_code` varchar(255) DEFAULT NULL,
`deleted_flag` tinyint NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
UNIQUE KEY `ak_salary` (`employee_id`,`from_date`,`to_date`),
KEY `idx_employee_id` (`employee_id`),
KEY `idx_salary_amount` (`salary_amount`),
CONSTRAINT `salary_ibfk_1` FOREIGN KEY (`employee_id`) REFERENCES `employee` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2844050 DEFAULT CHARSET=utf8mb3
CREATE TABLE `invoice` (
`id` int unsigned NOT NULL AUTO_INCREMENT,
`employee_id` int unsigned NOT NULL,
`invoiced_date` date NOT NULL,
`paid_flag` tinyint NOT NULL DEFAULT '0',
`insert_dt` datetime NOT NULL,
`insert_user_id` int NOT NULL DEFAULT '-1',
`insert_process_code` varchar(255) DEFAULT NULL,
`update_dt` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`update_user_id` int NOT NULL DEFAULT '-1',
`update_process_code` varchar(255) DEFAULT NULL,
`deleted_flag` tinyint NOT NULL DEFAULT '0',
PRIMARY KEY (`id`,`invoiced_date`),
KEY `idx_employee_id` (`employee_id`)
) ENGINE=InnoDB AUTO_INCREMENT=973489 DEFAULT CHARSET=utf8mb3
/*!50100 PARTITION BY RANGE (year(`invoiced_date`))
SUBPARTITION BY HASH (month(`invoiced_date`))
SUBPARTITIONS 12
(PARTITION p1984 VALUES LESS THAN (1985) ENGINE = InnoDB,
PARTITION p1985 VALUES LESS THAN (1986) ENGINE = InnoDB,
PARTITION p1986 VALUES LESS THAN (1987) ENGINE = InnoDB,
PARTITION p1987 VALUES LESS THAN (1988) ENGINE = InnoDB,
PARTITION p1988 VALUES LESS THAN (1989) ENGINE = InnoDB,
PARTITION p1989 VALUES LESS THAN (1990) ENGINE = InnoDB,
PARTITION p1990 VALUES LESS THAN (1991) ENGINE = InnoDB,
PARTITION p1991 VALUES LESS THAN (1992) ENGINE = InnoDB,
PARTITION p1992 VALUES LESS THAN (1993) ENGINE = InnoDB,
PARTITION p1993 VALUES LESS THAN (1994) ENGINE = InnoDB,
PARTITION pOTHER VALUES LESS THAN MAXVALUE ENGINE = InnoDB) */
SELECT
salary.employee_id,
salary.salary_amount,
salary.from_date,
salary.to_date
FROM sample_staff.salary
LIMIT 10;
/*
+-------------+---------------+------------+------------+
| employee_id | salary_amount | from_date | to_date |
+-------------+---------------+------------+------------+
| 10001 | 60117.00 | 1986-06-26 | 1987-06-26 |
| 10001 | 62102.00 | 1987-06-26 | 1988-06-25 |
| 10001 | 66074.00 | 1988-06-25 | 1989-06-25 |
| 10001 | 66596.00 | 1989-06-25 | 1990-06-25 |
| 10001 | 66961.00 | 1990-06-25 | 1991-06-25 |
| 10001 | 71046.00 | 1991-06-25 | 1992-06-24 |
| 10001 | 74333.00 | 1992-06-24 | 1993-06-24 |
| 10001 | 75286.00 | 1993-06-24 | 1994-06-24 |
| 10001 | 75994.00 | 1994-06-24 | 1995-06-24 |
| 10001 | 76884.00 | 1995-06-24 | 1996-06-23 |
+-------------+---------------+------------+------------+
*/
SELECT
invoice.invoiced_date,
invoice.employee_id
FROM sample_staff.invoice
limit 10;
/*
+---------------+-------------+
| invoiced_date | employee_id |
+---------------+-------------+
| 1985-12-01 | 10009 |
| 1985-12-01 | 10013 |
| 1985-12-01 | 10048 |
| 1985-12-01 | 10064 |
| 1985-12-01 | 10070 |
| 1985-12-01 | 10098 |
| 1985-12-01 | 10126 |
| 1985-12-01 | 10137 |
| 1985-12-01 | 10144 |
| 1985-12-01 | 10195 |
+---------------+-------------+
*/
I found a solution.我找到了解决方案。 Hopefully it is the right one.希望这是正确的。
I ended up adding a field to the salary table, named invoice_id, which defaults to -1 but has an invoice.id (one of them) that fulfill the conditions of the INNER JOIN我最终在工资表中添加了一个名为 invoice_id 的字段,该字段默认为 -1,但具有满足 INNER JOIN 条件的 invoice.id(其中之一)
salary.employee_id = invoice.employee_id
AND invoice.invoiced_date BETWEEN salary.from_date AND salary.to_date
so now the INNER JOIN is所以现在 INNER JOIN 是
INNER JOIN sample_staff.invoice ON 1=1
AND invoice.id = salary.invoice_id
and added a WHERE clause at the end of the query并在查询末尾添加了 WHERE 子句
WHERE 1=1
AND salary.invoice_id > 0
Now the query finished in 58 seconds, whereas previously it did not finished in 60 seconds (Workbench aborted after 60 seonds)现在查询在 58 秒内完成,而之前它没有在 60 秒内完成(工作台在 60 秒后中止)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.