mariadb:强制“SELECT STRAIGHT_JOIN”作为默认参数

时间:2017-03-23 13:51:18

标签: mariadb percona

我目前将数据从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;

EXPLAIN MariaDB

EXPLAIN IN PRODUCTION (Percona)

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`,以便我们了解正在发生的事情。 通常优化和“复合”索引一样好。

我意识到我没有回答你提出的问题。但我宁愿先做上面的清理工作。