我有一个旧的MySQL查询来查找始终正常工作的免费ID(0.0325秒)。但现在我已经改为MariaDB,而且速度非常慢(超过30秒)
SELECT
START AS codice
FROM (
SELECT
codice +1 AS START
FROM `clfoco`
WHERE
SUBSTRING(codice,9) BETWEEN '0000001' AND '9999999' AND codice LIKE '1201__%'
) AS a
LEFT JOIN (
SELECT
codice
FROM `clfoco`
WHERE
SUBSTRING(codice,9) BETWEEN '0000001' AND '9999999' AND codice LIKE '1201__%'
) AS b ON a.start = b.codice
WHERE b.codice IS NULL
LIMIT 1
" codice"是主要指标
旧数据库是MySQL 5.1.73 ,新数据库是MariaDB 5.5.52 。
我已经复制了表(导入/导出数据库和数据),删除并重新创建了索引,但新数据库中的查询总是很慢。
我已经阅读了更改索引(codice + 1)打破索引并强制MySQL扫描整个表的答案,但我不认为是这种情况,因为在旧MySQL数据库中查询速度很快。
有什么建议吗?
修改
表
CREATE TABLE IF NOT EXISTS `clfoco` (
`codice` varchar(20) NOT NULL,
`id_anagra` int(9) NOT NULL,
`descri` varchar(100) DEFAULT NULL,
....
....
....
PRIMARY KEY (`codice`),
KEY `id_anagra` (`id_anagra`),
FULLTEXT KEY `descri` (`descri`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
向Maria Db解释
| id|select_type|table |type |possible_keys|key |key_len|ref |rows |Extra
------------------------------------------------------------------------------
| 1 | SIMPLE |clfoco|range |PRIMARY |PRIMARY |62 |NULL|24549 |Using where; Using index
| 1 | SIMPLE |clfoco|index |PRIMARY |PRIMARY |62 |NULL|25182 |Using where; Using index; Using join buffer (flat, BNL join)
用Mysql 5.1.73
解释| id|select_type|table |type |possible_keys|key |key_len|ref |rows |Extra
------------------------------------------------------------------------------
| 1 |PRIMARY |<derived2> |ALL |NULL |NULL |NULL |NULL|24661
| 1 |PRIMARY |<derived3> |ALL |NULL |NULL |NULL |NULL|24661 |Using where; Not exists
| 3 | DERIVED |clfoco |index |PRIMARY |PRIMARY |62 |NULL|25182 |Using where; Using index
| 2 | DERIVED |clfoco |index |PRIMARY |PRIMARY |62 |NULL|25182 |Using where; Using index;
新编辑
在Rick James的建议之后我改变了查询。
SELECT a.codice+1 AS START
FROM `clfoco` a
WHERE codice LIKE '1201__%'
AND(substring(b.codice,9) between '0000001' and '9999999')
AND NOT EXISTS (
SELECT *
FROM `clfoco`
WHERE codice LIKE '1201__%'
AND (substring(b.codice,9) between '0000001' and '9999999')
AND codice = a.codice+1 )
LIMIT 1;
MariaDB上的执行时间为0.0294秒
EXPLAIN EXTENDED:
id|select_type |table |type |possible_keys|key |key_len|ref |rows |filtered|Extra
1 |PRIMARY |a |range|PRIMARY |PRIMARY|62 |NULL|24549 |100.00 |Using where; Using index
2 |DEPENDENT SUBQUERY|clfoco|range|PRIMARY |PRIMARY|62 |NULL|24549 |100.00 |Range checked for each record (index map: 0x1)
答案 0 :(得分:0)
子选择似乎有点混淆,这总是很危险,因为即使它现在不会混淆优化器,它也可能在未来版本中(似乎已经发生)。我会写这个,没有子选择:
select a.codice+1 as codice
from clfoco a
left join clfoco b
on b.codice=a.codice+1
and (substring(b.codice,9) between '0000001' and '9999999')
and b.codice like '1201__%'
where b.codice is null
and (substring(a.codice,9) between '0000001' and '9999999')
and a.codice like '1201__%'
limit 1;
这会使优化器更容易混淆吗?
从你添加的NOT EXISTS版本的解释中,看起来它正在使用like '1201__%'
来索引依赖子查询,而不应该这样做。试试这个:
select a.codice+1 as codice
from clfoco a
left join clfoco b on b.codice=a.codice+1
where b.codice is null
and (substring(a.codice,9) between '0000001' and '9999999')
and a.codice like '1201__%'
and (substring(a.codice+1,9) between '0000001' and '9999999')
and a.codice+1 like '1201__%'
limit 1;
答案 1 :(得分:0)
SELECT a.codice+1 AS START
FROM `clfoco` a
WHERE codice LIKE '1201__%'
AND NOT EXISTS (
SELECT *
FROM `clfoco`
WHERE codice LIKE '1201__%'
AND codice = a.codice+1 )
LIMIT 1;
注意:
EXISTS
可以更好地进行优化。 (但你的版本很老了。)SUBSTRING
妨碍了索引的使用。SUBSTRING
支票似乎没用。codice
需要VARCHAR
,否则LIKE
会有问题。请提供SHOW CREATE TABLE
和EXPLAIN SELECT ...
。