我有一个生成SQL的框架。其中一个查询是使用我的索引" A"并在7秒内返回结果。我看到我可以优化这个并且我创建了一个索引" B"。
现在,如果我运行"解释我的查询",它仍然使用我的索引A.但是,如果我强制使用索引B,我得到我的结果1秒(快7倍)
很明显我的索引B比我的索引A快。我不能使用" force index"或"使用索引"命令,因为我的sql是从不支持此功能的框架生成的。
那么,为什么mysql不能自然地使用最快的索引。有没有办法告诉mysql总是使用某个索引而不添加"使用"或者"强迫"。
查询:
SELECT *
FROM soumission
LEFT OUTER JOIN region_administrative
ON soumission.region_administrative_oid=region_administrative.oid
WHERE (soumission.statut=2
AND ((soumission.telephone LIKE '%007195155134070067132211046052045128049212213255%'
OR (soumission.autre_telephone LIKE '%007195155134070067132211046052045128049212213255%'))
OR (soumission.cellulaire LIKE '%007195155134070067132211046052045128049212213255%')))
ORDER BY soumission.date_confirmation DESC, soumission.numero;
我在多栏上添加了一个索引" statut","电话"," autre_telephone"," cellulaire"
如果我强制使用这个索引,我的查询速度提高了7倍,但如果我没有指定使用哪个索引,它会使用另一个索引(仅限于法定字段),这个速度要慢7倍
这里是解释我选择一个大的日期(使用错误的索引)
答案 0 :(得分:0)
这似乎就是你在做什么......
SELECT s.*, ra.*
FROM soumission AS s
LEFT OUTER JOIN region_administrative AS ra ON s.region_administrative_oid=ra.oid
WHERE s.statut = 2
AND ( s.telephone LIKE '%007195155134070067132211046052045128049212213255%'
OR s.autre_telephone LIKE '%007195155134070067132211046052045128049212213255%'
OR s.cellulaire LIKE '%007195155134070067132211046052045128049212213255%'
)
ORDER BY s.date_confirmation DESC, s.numero;
如果您不需要ra.*
,请摆脱LEFT JOIN
。
您建议的多列索引是无用的,除非...... statut = 2
少于20%的行,否则不会被使用。在这种情况下,它只会使用索引的第一列。
OR
打败索引。 (见下文)
LIKE
上的前导通配符会失败索引。你需要领先或尾随外卡吗?
DESC
中ASC
和ORDER BY
的混合使用索引来避免排序。
那么,该怎么办?而不是为3个电话号码设置3列,而是有另一个电话号码表。然后为给定的输出提供任意数量的行。然后搜索该表可能会更快,因为避免OR
- 但前提是你摆脱了前导通配符。
(这是一个非常长的电话号码!这是真的吗?)
答案 1 :(得分:0)
关于查询本身:
所以,创建这些索引:
ALTER TABLE `region_administrative` ADD INDEX `region_administrativ_idx_oid` (`oid`);
ALTER TABLE `soumission` ADD INDEX `soumission_idx_statut_oid_cellulaire` (`statut`,`region_administrative_oid`,`cellulaire`);
ALTER TABLE `soumission` ADD INDEX `soumission_idx_statut_oid_telephone` (`statut`,`region_administrative_oid`,`autre_telephone`);
ALTER TABLE `soumission` ADD INDEX `soumission_idx_statut_oid_telephone` (`statut`,`region_administrative_oid`,`telephone`);
然后尝试此查询:
SELECT
*
FROM
((SELECT
*
FROM
soumission
LEFT OUTER JOIN
region_administrative
ON soumission.region_administrative_oid = region_administrative.oid
WHERE
(
soumission.statut = 2
AND (
(
soumission.cellulaire LIKE '007195155134070067132211046052045128049212213255%'
)
)
)
ORDER BY
soumission.date_confirmation DESC,
soumission.numero)
UNION
DISTINCT (SELECT
*
FROM
soumission
LEFT OUTER JOIN
region_administrative
ON soumission.region_administrative_oid = region_administrative.oid
WHERE
(soumission.statut = 2
AND (((soumission.autre_telephone LIKE '007195155134070067132211046052045128049212213255%'))))
ORDER BY
soumission.date_confirmation DESC,
soumission.numero)
UNION
DISTINCT (SELECT
*
FROM
soumission
LEFT OUTER JOIN
region_administrative
ON soumission.region_administrative_oid = region_administrative.oid
WHERE
(soumission.statut = 2
AND ((soumission.telephone LIKE '007195155134070067132211046052045128049212213255%')))
ORDER BY
soumission.date_confirmation DESC,
soumission.numero)
) AS union1
ORDER BY
union1.date_confirmation DESC,
union1.numero