我从MariaDB迁移到Mysql。我下面的查询在Mysql中花费超过三分钟,而在MariaDB中花费不到一分钟。 Mysql版本是5.7。 请提出我该如何解决这个问题,非常感谢!!!
SELECT
COUNT(*)
FROM
(SELECT i.*, f.*, c.*, ft.*, -- summarized for readability
(SELECT f1.id
FROM sys_exten_flow_task f1
WHERE f1.instance_id = f.INSTANCE_ID AND state = '1'
ORDER BY f1.update_date DESC
LIMIT 0 , 1) AS pretaskid,
CASE
WHEN i.FLOW_DEFINE IS NULL THEN 'free'
ELSE i.FLOW_DEFINE
END AS fd,
CASE
WHEN f.TASK_DEFINE_ID IS NULL THEN 'free'
ELSE f.TASK_DEFINE_ID
END AS tdi
FROM
sys_exten_flow_task f, sys_exten_flow_instance i,
sys_exten_flow_define_task dt, sys_user c, sys_dict ft
WHERE
i.ID = f.INSTANCE_ID
AND i.CREATE_BY = c.ID
AND i.FLOW_TYPE = ft.ID
AND dt.id = f.task_define_id) a;
+----------+
| count(*) |
+----------+
| 3841309 |
+----------+
1 row in set (3 min 21.97 sec)
说明计划
+----+--------------------+------------+------------+--------+--------------------------------------------------+------------------------+---------+----------------------------+---------+----------+---------------------------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+--------------------+------------+------------+--------+--------------------------------------------------+------------------------+---------+----------------------------+---------+----------+---------------------------------------+
| 1 | PRIMARY | <derived2> | NULL | ALL | NULL | NULL | NULL | NULL | 3640604 | 100.00 | NULL |
| 2 | DERIVED | i | NULL | ALL | PRIMARY,CREATE_BY | NULL | NULL | NULL | 788059 | 100.00 | Using where |
| 2 | DERIVED | ft | NULL | eq_ref | PRIMARY,ID | PRIMARY | 258 | scdxoa.i.FLOW_TYPE | 1 | 100.00 | Using where |
| 2 | DERIVED | c | NULL | eq_ref | PRIMARY,ID | PRIMARY | 258 | scdxoa.i.CREATE_BY | 1 | 100.00 | NULL |
| 2 | DERIVED | f | NULL | ref | INDEX_TASK_INSTANCE_ID,INDEX_TASK_TASK_DEFINE_ID | INDEX_TASK_INSTANCE_ID | 402 | scdxoa.i.ID | 4 | 100.00 | Using index condition; Using where |
| 2 | DERIVED | dt | NULL | eq_ref | PRIMARY | PRIMARY | 258 | scdxoa.f.TASK_DEFINE_ID | 1 | 100.00 | Using where |
| 3 | DEPENDENT SUBQUERY | f1 | NULL | ref | INDEX_TASK_STATUS,INDEX_TASK_INSTANCE_ID,INDEX | INDEX | 408 | const,scdxoa.f.INSTANCE_ID | 3 | 100.00 | Using index condition; Using filesort |
+----+--------------------+------------+------------+--------+--------------------------------------------------+------------------------+---------+----------------------------+---------+----------+---------------------------------------+
7 rows in set, 2 warnings (0.01 sec)
我在MariaDB中执行相同的查询,
+----------+
| count(*) |
+----------+
| 3912445 |
+----------+
1 row in set (56.54 sec)
说明计划
+------+--------------------+-------+--------+--------------------------------------------------+------------------------+---------+-------------------------+-------+----------+------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+------+--------------------+-------+--------+--------------------------------------------------+------------------------+---------+-------------------------+-------+----------+------------------------------------+
| 1 | PRIMARY | c | index | PRIMARY,ID | group_login_name | 205 | NULL | 23047 | 100.00 | Using index |
| 1 | PRIMARY | i | ref | PRIMARY,CREATE_BY | CREATE_BY | 259 | scdxoa.c.ID | 15 | 100.00 | |
| 1 | PRIMARY | ft | eq_ref | PRIMARY,ID | PRIMARY | 258 | scdxoa.i.FLOW_TYPE | 1 | 100.00 | Using where; Using index |
| 1 | PRIMARY | f | ref | INDEX_TASK_INSTANCE_ID,INDEX_TASK_TASK_DEFINE_ID | INDEX_TASK_INSTANCE_ID | 402 | scdxoa.i.ID | 2 | 100.00 | Using index condition; Using where |
| 1 | PRIMARY | dt | eq_ref | PRIMARY | PRIMARY | 258 | scdxoa.f.TASK_DEFINE_ID | 1 | 100.00 | Using where; Using index |
| 3 | DEPENDENT SUBQUERY | f1 | ref | INDEX_TASK_STATUS,INDEX_TASK_INSTANCE_ID,INDEX | INDEX_TASK_INSTANCE_ID | 402 | scdxoa.f.INSTANCE_ID | 2 | 100.00 | Using where; Using filesort |
+------+--------------------+-------+--------+--------------------------------------------------+------------------------+---------+-------------------------+-------+----------+------------------------------------+
6 rows in set, 2 warnings (0.00 sec)
我还尝试让Mysql对mariadb的结果sql进行优化。
select count(0) AS "count(*)"
from "scdxoa"."sys_exten_flow_task" "f"
join "scdxoa"."sys_exten_flow_instance" "i"
join "scdxoa"."sys_exten_flow_define_task" "dt"
join "scdxoa"."sys_user" "c"
join "scdxoa"."sys_dict" "ft"
where (("scdxoa"."i"."CREATE_BY" = "scdxoa"."c"."ID")
and ("scdxoa"."i"."ID" = "scdxoa"."f"."INSTANCE_ID")
and ("scdxoa"."i"."FLOW_TYPE" = "scdxoa"."ft"."ID")
and ("scdxoa"."dt"."ID" = "scdxoa"."f"."TASK_DEFINE_ID"));
+----------+
| count(*) |
+----------+
| 3841309 |
+----------+
1 row in set (21.83 sec)
答案 0 :(得分:0)
此构造浪费了一些时间:
SELECT COUNT(*)
FROM ( SELECT lots-of-columns
FROM, etc )
不仅仅是简单地
SELECT COUNT(*)
FROM, etc
这是因为已建立派生表并将其放入临时表中(可能是您的情况下放在磁盘上),然后进行计数。
由于我没有在MariaDB的EXPLAIN
中看到“ 2”,所以我猜测他们为您做了优化。
在5.6和10.0时,他们在优化器中出现了一些明显的差异。您遇到了MariaDB大放异彩的情况。
将第一个CASE..END
简化为IFNULL(i.FLOW_DEFINE, 'free')
;等
请使用JOIN..ON
而不是逗号+ WHERE-这不会提高速度,但可能有助于提高可读性。
即使在子查询中,也有其他简化;例如,CASE对COUNT不提供任何服务。无论您是否在乎,如果您提供了一个最小的测试案例来证明问题所在,那么我们可能会提供更多帮助。