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

问题描述 投票:0回答:1

我目前将数据从 Percona 5.5.14 迁移到 MariaDB 10.1.22

在使用某些 JOIN 的特定查询上,两个版本之间的查询计划不同,并且响应时间 > 400 毫秒

我找到解决此问题的唯一解决方案是使用 STRAIGHT_JOIN 选项:

Percona 5.5.14 => 150ms

MariaDB 10.1.22 => 550ms ==> 150ms(带 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)

mariadb percona
1个回答
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
从“commajoin”更改为
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
OR
, and perhaps allowing
INDEX(前缀)` 才有用。

注意

LENGTH()
byte长度;
CHAR_LENGTH()
字符 长度。

你所有的

IDs
都是
BIGINT
吗?你真的需要那么大的范围吗?缩小数据类型将有助于提高性能。

我明白了

Using intersect
。请提供
SHOW CREATE TABLE
ZPE`,以便我们了解发生了什么。 通常优化不如不如拥有“复合”索引。

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

© www.soinside.com 2019 - 2024. All rights reserved.