Reputation: 413
This query takes 1.2 seconds:
select * from alert limit 10000;
This query takes 33.99 seconds:
select * from alert_version limit 10000;
alert_version is a view, which is basically the "alert" table with a subquery:
select `alert`.`Alert_UID` AS `Alert_UID`,`alert`.`Rule_Name` AS `Rule_Name`,
`alert`.`Headline` AS `Headline`,`alert`.`Severity` AS `Severity`,
`alert`.`Device_UID` AS `Device_UID`,`alert`.`Configuration_Set_ID` AS `Configuration_Set_ID`,
`alert`.`Instance_UID` AS `Instance_UID`,`alert`.`Create_DateTime` AS `Create_DateTime`,
`alert`.`Delete_DateTime` AS `Delete_DateTime`,
( SELECT `version_build`.`Version`
from `version_build`
where ((`version_build`.`Instance_UID` = `alert`.`Instance_UID`)
and (`version_build`.`Create_DateTime` >= `alert`.`Create_DateTime`)
)
order by `version_build`.`Create_DateTime`
limit 1
) AS `version`
from `alert`
When I run EXPLAIN on this query, I get:
+----+--------------------+---------------+------+-----------------------------------------------------------------------------------+--------------------------+---------+----------------------------+--------+------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+--------------------+---------------+------+-----------------------------------------------------------------------------------+--------------------------+---------+----------------------------+--------+------------------------------------------+
| 1 | PRIMARY | alert | ALL | NULL | NULL | NULL | NULL | 301274 | NULL |
| 2 | DEPENDENT SUBQUERY | version_build | ref | uid_version_build_create,version_build_Instance_UID,version_build_Create_DateTime | uid_version_build_create | 110 | insight.alert.Instance_UID | 6 | Using where; Using index; Using filesort |
+----+--------------------+---------------+------+-----------------------------------------------------------------------------------+--------------------------+---------+----------------------------+--------+------------------------------------------+
So, what do you think I should do to get acceptable performance?
UPDATE:
Per request, adding table information:
CREATE TABLE `alert` (
`Alert_UID` varchar(36) NOT NULL,
`Rule_Name` varchar(80) DEFAULT NULL,
`Headline` varchar(255) DEFAULT NULL,
`Severity` varchar(12) DEFAULT NULL,
`Device_UID` varchar(36) NOT NULL,
`Configuration_Set_ID` varchar(12) DEFAULT NULL,
`Instance_UID` varchar(36) NOT NULL,
`Create_DateTime` timestamp NOT NULL,
`Delete_DateTime` timestamp NULL DEFAULT NULL,
PRIMARY KEY (`Alert_UID`),
KEY `alert_Create_DateTime` (`Alert_UID`,`Create_DateTime`),
KEY `alert_Headline` (`Headline`),
KEY `alert_Rule_Headline` (`Rule_Name`,`Headline`),
KEY `alert_Instance_UID` (`Instance_UID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 |
CREATE TABLE `version_build` (
`Instance_UID` varchar(36) NOT NULL,
`Version` varchar(12) NOT NULL,
`Build` varchar(30) DEFAULT NULL,
`Create_DateTime` timestamp NOT NULL,
UNIQUE KEY `uid_version_build_create`
(`Instance_UID`,`Version`,`Build`,`Create_DateTime`),
KEY `version_build_Instance_UID` (`Instance_UID`),
KEY `version_build_Create_DateTime` (`Create_DateTime`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 |
Upvotes: 0
Views: 81
Reputation: 2261
Please test carefully! I only made some quick test
From my point of view the subquery is just an overkill in this query (so the performances are horrible):
SELECT
`alert`.`Alert_UID` AS `Alert_UID`,
`alert`.`Rule_Name` AS `Rule_Name`,
`alert`.`Headline` AS `Headline`,
`alert`.`Severity` AS `Severity`,
`alert`.`Device_UID` AS `Device_UID`,
`alert`.`Configuration_Set_ID` AS `Configuration_Set_ID`,
`alert`.`Instance_UID` AS `Instance_UID`,
`alert`.`Create_DateTime` AS `Create_DateTime`,
`alert`.`Delete_DateTime` AS `Delete_DateTime`,
`version_build`.`Version` AS `version`,
MIN(version_build.Create_DateTime)
FROM alert
LEFT JOIN version_build ON (alert.Instance_UID = version_build.Instance_UID
AND version_build.Create_DateTime >= alert.Create_DateTime)
GROUP BY alert.Alert_UID
Group-By is not order-wise so is necessary the trick of MIN in the select field otherwise the order is unpredictable. I didn't test the performance, but i guess they are a fraction of subquery.
Now with null values in case the join condition is not satisfied.
Upvotes: 1
Reputation: 142208
What will you do with 10K rows? That is usually too much for an app to handle.
Without an ORDER BY
, which 10K rows are you hoping to get? It is unpredictable. With an ORDER BY
, the query may be even slower.
The subquery is the performance killer. Live with the speed. However, you seem to be doing a "groupwise max" in an inefficient way. This index may help:
INDEX(Instance_UID, Create_DateTime, Version) -- in this order!
More on groupwise-max: http://mysql.rjweb.org/doc.php/groupwise_max
Upvotes: 2