Mariadb 使用修改的索引进行左慢速连接
我有一个旧的MySQL查询来查找一个始终运行良好的免费ID(0.0325秒)。但现在我换成了MariaDB,速度非常慢(超过30秒) “codice”是主要指标 旧数据库是MySQL 5.1.73,新数据库是MariaDB 5.5.52 我复制了表(导入/导出数据库和数据),删除并重新创建了索引,但新数据库中的查询总是很慢 我读过一些答案,其中更改的索引(codice+1)会破坏索引并强制MySQL扫描整个表,但我认为情况并非如此,因为在旧的MySQL数据库中,查询速度很快 有什么建议吗 编辑Mariadb 使用修改的索引进行左慢速连接,mariadb,Mariadb,我有一个旧的MySQL查询来查找一个始终运行良好的免费ID(0.0325秒)。但现在我换成了MariaDB,速度非常慢(超过30秒) “codice”是主要指标 旧数据库是MySQL 5.1.73,新数据库是MariaDB 5.5.52 我复制了表(导入/导出数据库和数据),删除并重新创建了索引,但新数据库中的查询总是很慢 我读过一些答案,其中更改的索引(codice+1)会破坏索引并强制MySQL扫描整个表,但我认为情况并非如此,因为在旧的MySQL数据库中,查询速度很快 有什么建议吗 编辑
桌子 与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进行解释
MariaDB上的执行时间为0.0294秒
解释扩展:
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)
子选择看起来有点模糊,这总是很危险的,因为即使它现在没有混淆优化器,它也可能在将来的版本中出现(就像已经发生的那样)。如果没有子选项,我会写这篇文章:
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版本的解释来看,它似乎在使用如'1201_u_%'
对依赖子查询进行索引,而它不应该这样做。试试这个:
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;
注:
可以更好地优化。(但是你的版本已经很旧了。)存在
妨碍了索引的使用子字符串
检查似乎没有用子字符串
必须是codice
,否则像VARCHAR
这样的
会有问题
请提供
SHOW CREATE TABLE
和EXPLAIN SELECT…
索引在使用之类的和/或基于函数的谓词的查询中无效。在旧服务器和新服务器子字符串上显示EXPLAIN SELECT…
的输出(codice,9)介于“0000001”和“9999999”之间
——不要在函数中隐藏列;它防止使用索引。由于该子句没有添加任何有用的内容,所以请将其全部删除。您可能遇到了Oracle optimizer比MariaDB做得更好的特定情况。让我们看看EXPLAIN SELECT…
。@gurvindersingh-INDEX(codice)
可用于此“范围”:codice类似于'1201%'
。codice是一个varchar(20),具有多个长度值和0个前导。(es:2000512,001244512011101211000000001)@user2380825你能试试我的查询,让我知道它是如何工作的(如果它不符合解释所说的)我的查询与Rick James的查询是等效的,只是他省略了子字符串…介于
位之间(你可能需要也可能不需要;我假设它是这样保留的)他用的是notexists,而我用的是等价的左JOIN+,其中。。。是空的,这对我来说总是更快。我只在有多个这样的子句和多个一对多关系的情况下使用EXISTS/NOT EXISTS。您好,您的查询比我的快,在MariaDB上12秒,但比我的查询慢得多MySql@user2380825解释说什么?可能会有帮助的事情(取决于索引出错的位置):使其选择“直接连接…”
或在clfoco a
和/或clfoco b
之后添加使用索引(什么是索引名)
。。。这很有趣。对于3个选择的解释中的2行。还请提供显示警告的输出代码>在解释扩展选择…(EXPLAIN EXTENDED SELECT…)之后立即执行代码>我怀疑有一个重要的查询重写正在进行。同时,我的公式是否“正确”且更快?您的查询是错误的(但非常快),结果是12010001,而它应该是1201100000001。我需要在一个编号为121010、121100、121200、1212000000000001的表中找到类似121xxxyyyyyyyyyyyyy的数字的累进形式(前8个数字是“tipology”,下一个是用户ID。解释扩展选择…;显示警告;使用PhpMyadmin在同一查询中完成。找不到行。#Rick James-将您的查询稍作更改为SELECT a.codice+1 as START FROM
clfoco`a,其中codice类似于'1201\%'和(substring(a.codice,9)介于'0000001'和'999999'之间)并且不存在(从clfoco
中选择*,其中密码类似于“1201”;(子字符串(a.codice,9)介于“0000001”和“999999”之间),密码=a.codice+1)限制1`
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;
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)
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;
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;
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;