我目前将数据从Percona 5.5.14迁移到MariaDB 10.1.22
在使用某些JOIN的特定查询中,2个版本和响应时间之间的查询计划不同> 400ms的
我找到解决此问题的唯一解决方案是使用STRAIGHT_JOIN选项:
Percona 5.5.14 => 150ms的
MariaDB 10.1.22 => 550ms ==> 150毫秒带有STRAIGHT_JOIN选项
我的问题是:是否有一个参数在每个使用JOIN的SELECT查询上强制使用STRAIGHT_JOIN选项?
我知道这不是一个好的解决方案,但我想知道它是否存在,因为我还没找到它
查询是在存储过程中调用的:
SELECT
C.NAME AS out_Name,
RC.ID AS out_PlanId,
ISO.A3 AS out_A3,
ISO.NAME AS out_CountryName,
ISO.NUMBER AS out_countryNumber,
C.ID AS out_CId,
RC.NAME AS out_CName,
RSG.NAME AS out_ServiceGroupName,
SPE.id AS out_EntryId,
SPE.GOUPID AS out_GroupId,
ZPE.ZONEID AS out_zoneId,
Z.NAME AS out_zoneName,
ZPE.ID AS out_zoneEntryId,
ZPE.PREFIX AS out_zonePrefix,
RC.PLANID AS out_zonePlanId,
SPE.ZONEID AS out_zoneGroupId,
ZSG.NAME AS out_zoneGroupName,
SCPA.ID AS out_scpAId,
SCPA.NAME AS out_scpAName,
ZG.ID AS out_zoningpId,
ZG.NAME AS out_zoningName,
IFNULL(SF1.NAME,"") AS out_Flag_serviceType_name,
IFNULL(SF2.NAME,"") AS out_Flag_service_name,
IFNULL(SF3.NAME,"") AS out_Flag_zone_name,
IFNULL(SF4.NAME,"") AS out_Flag_Plan_name,
RC.RULEID AS out_ruleId,
RP.NAME AS out_ruleName
FROM
table1 AS M ,
table2 AS C,
table3 AS RC,
table3 AS RP,
table4 AS SPE LEFT JOIN table12 AS SF2 ON SF2.id=SPE.FLAGID,
table5 AS ST LEFT JOIN table11 AS SF1 ON SF1.id=ST.FLAGID,
table6 AS RSG,
table7 AS ZSG,
table8 AS ZPE LEFT JOIN table14 as SF4 on SF4.id=ZPE.FLAGID,
table9 AS ISO,
table10 AS NP,
table11 AS Z LEFT JOIN table13 as SF3 on SF3.id=Z.FLAGID ,
table12 AS SCPA,
table13 AS ZG
WHERE
M.name ='TSL'
AND C.mvno_id =M.id
AND C.id ='1010'
AND RC.id =C.ID
AND RP.id =RC.RULEID
AND SPE.SERVICEID =RC.SERVICEID
AND RSG.ID =SPE.GOUP_ID
AND ST.NAME ='GOR'
AND SPE.SERVICETYPE_ID =ST.ID
AND ZSG.ID =SPE.ZONEID
AND ZPE.ZONE_PLAN_ID =RC.PLANID
AND NP.NAME ='OSI'
AND ZPE.NUMBERINGPLAN_ID =NP.ID
AND ZPE.ISOCOUNTRY_ID =ISO.ID
AND ZPE.ZONEID =ZSG.ID
AND Z.ID =ZPE.ZONEID
AND SCPA.ID =Z.ACTIONID
AND ZG.ID =Z.GROUPID
AND ZSG.ID =ZPE.ZONEID
AND UNIX_TIMESTAMP()
BETWEEN UNIX_TIMESTAMP(IFNULL(ZPE.VALIDFROM,0))
AND UNIX_TIMESTAMP(IFNULL(ZPE.VALIDUNTIL,"2038-01-01") )
AND (
(
'0'=0
AND ZPE.PREFIX ='AUT'
)
OR
( '0'=1
AND
(
substring('AUT',1,1)=ZPE.prefix
OR substring('AUT',1,2)=ZPE.prefix
OR substring('AUT',1,3)=ZPE.prefix
OR substring('AUT',1,4)=ZPE.prefix
OR substring('AUT',1,5)=ZPE.prefix
OR substring('AUT',1,6)=ZPE.prefix
OR substring('AUT',1,7)=ZPE.prefix
OR substring('AUT',1,8)=ZPE.prefix
OR substring('AUT',1,9)=ZPE.prefix
OR substring('AUT',1,10)=ZPE.prefix
OR substring('AUT',1,11)=ZPE.prefix
OR substring('AUT',1,12)=ZPE.prefix
OR substring('AUT',1,13)=ZPE.prefix
OR substring('AUT',1,14)=ZPE.prefix
OR substring('AUT',1,15)=ZPE.prefix
OR concat('AUT','#') =ZPE.prefix
)
)
)
ORDER BY LENGTH(prefix) DESC
LIMIT 1;
答案 0 :(得分:0)
在LEFT JOINs
周围放置括号以确保它们被正确解析并且两个版本都相同:
( table4 AS SPE LEFT JOIN table12 AS SF2 ON SF2.id=SPE.FLAGID ),
( table5 AS ST LEFT JOIN table11 AS SF1 ON SF1.id=ST.FLAGID ),
同时,将JOINs
从“逗号”更改为JOIN .. ON
。这将使阅读更容易。并且,尤其是,明确WHERE
中的内容。
由于您显然正在生成SQL,因此稍微努力避免使用'0'=1
之类的构造。
substring('AUT',1,1)=ZPE.prefix OR substring('AUT',1,2)=ZPE.prefix OR ...
更简单地写成ZPE.prefix = left('AUT', CHAR_LENGTH(ZPE.prefix
))? Once you have change to that, you can probably further simplify that expression, probably getting rid of the other side of the
或, and perhaps allowing
INDEX(前缀)`才有用。
请注意LENGTH()
是字节的长度; CHAR_LENGTH()
是字符长度。
您的所有IDs
都是BIGINT
?你真的需要这么多范围吗?缩小数据类型将有助于提高性能。
我看到Using intersect
。请提供SHOW CREATE TABLE
ZPE`,以便我们了解正在发生的事情。 通常优化不和“复合”索引一样好。
我意识到我没有回答你提出的问题。但我宁愿先做上面的清理工作。