如今,您经常读到“ MariaDB是MySQL的替代品”。但实际上,有时会存在巨大差异。例如。这个:
有一个使用MariaDB查询的应用程序运行良好。现在必须使用MySQL,而且令人惊讶的是性能不足。
如何在MySQL上达到相同的性能?
我是否缺少任何设置?使用mariadb,它可以快速运行。
我应该修改查询吗?
那么最好的查询是什么?
该查询确定当前值和一年前的值,但是每天没有值,因此将搜索距一年前最近的日期。
这是查询。下面是创建一些测试数据的代码。
SELECT c.id, c.nname as n, a.wert as x,
(SELECT z.wert FROM tbl_history z
WHERE z.indize_id = a.indize_id
AND z.hdate > DATE_SUB(a.hdate, INTERVAL 1 YEAR)
ORDER BY z.hdate LIMIT 1
) as y
FROM tbl_history a
LEFT JOIN tbl_indize c ON a.indize_id = c.id
WHERE a.hdate =
(SELECT b.hdate FROM tbl_history b
WHERE b.indize_id = a.indize_id ORDER BY b.hdate DESC LIMIT 1)
AND a.indize_id = 1;
执行时间
MariaDB:0.01秒
的MySQL:12.23秒
这是一些虚拟数据
CREATE TABLE tbl_indize (
id int(11) NOT NULL AUTO_INCREMENT,
nname varchar(145) NOT NULL,
PRIMARY KEY (id)
);
CREATE TABLE tbl_history (
id int(11) NOT NULL AUTO_INCREMENT,
indize_id int(11) NOT NULL,
hdate date NOT NULL,
wert decimal(18,6) DEFAULT NULL,
PRIMARY KEY (id),
UNIQUE KEY idx_id_date (indize_id,hdate)
);
INSERT INTO tbl_indize (nname) values ('test');
INSERT INTO tbl_history (indize_id, hdate, wert) values (1, '1970-01-01', RAND());
INSERT INTO tbl_history (indize_id, hdate, wert) SELECT indize_id, date_add(hdate, INTERVAL 4096 DAY), SQRT(wert * RAND()) FROM tbl_history;
INSERT INTO tbl_history (indize_id, hdate, wert) SELECT indize_id, date_add(hdate, INTERVAL 2048 DAY), SQRT(wert * RAND()) FROM tbl_history;
INSERT INTO tbl_history (indize_id, hdate, wert) SELECT indize_id, date_add(hdate, INTERVAL 1024 DAY), SQRT(wert * RAND()) FROM tbl_history;
INSERT INTO tbl_history (indize_id, hdate, wert) SELECT indize_id, date_add(hdate, INTERVAL 512 DAY), SQRT(wert * RAND()) FROM tbl_history;
INSERT INTO tbl_history (indize_id, hdate, wert) SELECT indize_id, date_add(hdate, INTERVAL 256 DAY), SQRT(wert * RAND()) FROM tbl_history;
INSERT INTO tbl_history (indize_id, hdate, wert) SELECT indize_id, date_add(hdate, INTERVAL 128 DAY), SQRT(wert * RAND()) FROM tbl_history;
INSERT INTO tbl_history (indize_id, hdate, wert) SELECT indize_id, date_add(hdate, INTERVAL 64 DAY), SQRT(wert * RAND()) FROM tbl_history;
INSERT INTO tbl_history (indize_id, hdate, wert) SELECT indize_id, date_add(hdate, INTERVAL 32 DAY), SQRT(wert * RAND()) FROM tbl_history;
INSERT INTO tbl_history (indize_id, hdate, wert) SELECT indize_id, date_add(hdate, INTERVAL 16 DAY), SQRT(wert * RAND()) FROM tbl_history;
INSERT INTO tbl_history (indize_id, hdate, wert) SELECT indize_id, date_add(hdate, INTERVAL 8 DAY), SQRT(wert * RAND()) FROM tbl_history;
INSERT INTO tbl_history (indize_id, hdate, wert) SELECT indize_id, date_add(hdate, INTERVAL 4 DAY), SQRT(wert * RAND()) FROM tbl_history;
INSERT INTO tbl_history (indize_id, hdate, wert) SELECT indize_id, date_add(hdate, INTERVAL 2 DAY), SQRT(wert * RAND()) FROM tbl_history;
INSERT INTO tbl_history (indize_id, hdate, wert) SELECT indize_id, date_add(hdate, INTERVAL 1 DAY), SQRT(wert * RAND()) FROM tbl_history;
DELETE FROM tbl_history WHERE DAYOFWEEK(hdate) = 1;
DELETE FROM tbl_history WHERE DAYOFWEEK(hdate) = 2;
这是解释
玛丽亚数据库
+------+--------------------+-------+-------+---------------+-------------+---------+---------------+------+------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+--------------------+-------+-------+---------------+-------------+---------+---------------+------+------------------------------------+
| 1 | PRIMARY | a | ALL | idx_id_date | NULL | NULL | NULL | 5877 | Using where |
| 1 | PRIMARY | c | const | PRIMARY | PRIMARY | 4 | const | 1 | |
| 3 | DEPENDENT SUBQUERY | b | ref | idx_id_date | idx_id_date | 4 | t.a.indize_id | 2938 | Using where; Using index |
| 2 | DEPENDENT SUBQUERY | z | ref | idx_id_date | idx_id_date | 4 | t.a.indize_id | 2938 | Using index condition; Using where |
+------+--------------------+-------+-------+---------------+-------------+---------+---------------+------+------------------------------------+
的MySQL
+----+--------------------+-------+------------+-------+---------------+-------------+---------+---------------+------+----------+------------------------------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+--------------------+-------+------------+-------+---------------+-------------+---------+---------------+------+----------+------------------------------------------+
| 1 | PRIMARY | a | NULL | ALL | idx_id_date | NULL | NULL | NULL | 5877 | 99.57 | Using where |
| 1 | PRIMARY | c | NULL | const | PRIMARY | PRIMARY | 4 | const | 1 | 100.00 | NULL |
| 3 | DEPENDENT SUBQUERY | b | NULL | ref | idx_id_date | idx_id_date | 4 | t.a.indize_id | 1 | 100.00 | Using where; Using index; Using filesort |
| 2 | DEPENDENT SUBQUERY | z | NULL | ref | idx_id_date | idx_id_date | 4 | t.a.indize_id | 1 | 33.33 | Using index condition; Using filesort |
+----+--------------------+-------+------------+-------+---------------+-------------+---------+---------------+------+----------+------------------------------------------+
最佳答案
玩了之后,我发现了一个改进:
SELECT c.id, c.nname as n, a.wert as x,
(SELECT z.wert FROM tbl_history z
WHERE z.indize_id = a.indize_id
AND z.hdate > DATE_SUB(a.hdate, INTERVAL 1 YEAR)
ORDER BY z.hdate LIMIT 1
) as y
FROM tbl_history a
LEFT JOIN tbl_indize c ON a.indize_id = c.id
LEFT JOIN (SELECT MAX(hdate) as d, indize_id FROM tbl_history GROUP BY indize_id) x
ON x.indize_id = a.indize_id
WHERE a.hdate = x.d
AND a.indize_id = 1;
现在两个数据库的速度都可以。
MariaDB:0.00秒
MySQL:0.00秒
好吧-非常兼容^^
基本食谱
将where子句中的子选择替换为join-selects。
关于mysql - 如何重写SQL查询以在MariaDB和MySQL上实现相同的性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36165764/