0

考虑以下查询:

     SELECT
      `banner`.`id`,
      `region`.*
      FROM
     `nms_section_region_banner` AS `section`
      JOIN `aw_rbslider_slide_region` AS `region`
      ON
      FIND_IN_SET(
          region.region_id,
          section.region_id
        ) <> 0
       JOIN `aw_rbslider_banner` AS `banner`
         ON
      `section`.`banner_id` = `banner`.`id`
      JOIN `aw_rbslider_slide_banner` AS `slide_banner`
         ON
      `slide_banner`.`banner_id` = `banner`.`id`
      JOIN `aw_rbslider_slide` AS `slide`
         ON
      `slide_banner`.`slide_id` = `slide`.`id` AND `slide`.`status` = 1
      JOIN `aw_rbslider_slide_store` AS `store`
         ON
      `slide`.`id` = `store`.`slide_id`
         WHERE
      `section`.`section_id` = '414' AND(
      `region`.`region_type` = '1' OR FIND_IN_SET('400020', region.region_code) <> 0 OR 
      FIND_IN_SET(
        'PANINDIABEAUTY',
        region.region_code
      ) <> 0 OR FIND_IN_SET(
        'PANINDIADIGITAL',
        region.region_code
      ) <> 0 OR FIND_IN_SET('6210', region.region_code) <> 0 OR FIND_IN_SET(
        'PANINDIAJEWEL',
        region.region_code
      ) <> 0 OR FIND_IN_SET('MH', region.region_code) <> 0 OR FIND_IN_SET('Mumbai', 
       region.region_code) <> 0
       ) AND(
       `slide`.`display_from` <= '2021-07-23 02:05:16' OR `slide`.`display_from` IS NULL OR 
    `slide`.`display_from` = '0000-00-00 00:00:00'
     ) AND(
     `slide`.`display_to` >= '2021-07-23 02:05:16' OR `slide`.`display_to` IS NULL OR 
    `slide`.`display_to` = '0000-00-00 00:00:00'
    ) AND(
    `store`.`store_id` = '0' OR `store`.`store_id` = '2'
   )
   GROUP BY
 `banner`.`id`
   ORDER BY
   FIELD(
    region.region_type,
    3,
    2,
    5,
    4,
    1
  )

需要避免全表扫描。

我的查询是这样的,

图 1 和图 2 描述了表格的类型、键和可能的键信息

有人可以指导我避免对这 6 个表进行全表扫描。

4

1 回答 1

0

首先,进行一些清理,以便我可以查看并遵循您的查询和表的层次结构。接下来,您将针对区域代码使用一堆 FIND_IN_SET() 测试。从这意味着,您的区域代码是一长串多个值的容量,例如区域可能是“MH,400020,PANIDIAJEWEL,ETC”,因此您正在寻找区域代码中的一些“关键字”值。这是准确的吗?-- 或者 -- region_code 是否只有一个值。请确认。

随着您从部分到区域的加入,它们都只是“ID”键,不要使用 Find_In_Set(),而是直接相等。您不能基于函数优化连接(因此我的更改)并且可能是您查询的一个大问题

对于您的分组依据,您最初有banner.id,但由于通过连接已经等于section.banner_id,并且该部分是主表,因此部分表上的索引可以帮助优化该分组与辅助表。

 SELECT
        section.banner_id id,
        region.*
    FROM
        nms_section_region_banner section
            JOIN aw_rbslider_slide_region region
                ON section.region_id = region.region_id

            JOIN aw_rbslider_banner banner
                ON section.banner_id = banner.id

            JOIN aw_rbslider_slide_banner slide_banner
                ON section.banner_id = slide_banner.banner_id

                JOIN aw_rbslider_slide slide
                    ON slide_banner.slide_id = slide.id 
                    AND slide.status = 1
            
                JOIN aw_rbslider_slide_store store
                    ON slide_banner.slide_id = store.slide_id
                    -- if IDs are integer, dont wrap in quotes
                    AND ( store.store_id in ( 0, 2 ) )
    WHERE
            -- dont use quotes if IDs are actually numbers
            section.section_id = 414 

        AND (   -- unsure if region_type is integer vs string...
                region.region_type = '1' 
            OR  FIND_IN_SET( '400020', region.region_code ) <> 0 
            OR  FIND_IN_SET( 'PANINDIABEAUTY', region.region_code ) <> 0 
            OR  FIND_IN_SET( 'PANINDIADIGITAL', region.region_code ) <> 0 
            OR  FIND_IN_SET( '6210', region.region_code) <> 0 
            OR  FIND_IN_SET( 'PANINDIAJEWEL', region.region_code ) <> 0 
            OR  FIND_IN_SET( 'MH', region.region_code) <> 0 
            OR  FIND_IN_SET( 'Mumbai', region.region_code) <> 0 ) 

        AND (  slide.display_from IS NULL 
            OR slide.display_from = '0000-00-00 00:00:00' 
            OR slide.display_from <= '2021-07-23 02:05:16' ) 

        AND (  slide.display_to IS NULL 
            OR slide.display_to = '0000-00-00 00:00:00' 
            OR slide.display_to >= '2021-07-23 02:05:16' )

    GROUP BY
        section.banner_id
    ORDER BY
        FIELD( region.region_type,
                3,
                2,
                5,
                4,
                1 )

为了提供帮助,我确信主键上已经存在索引。但是,如果您有主 ID 的组合键和下一张表的键,那会有所帮助。此外,包含在 where/group 可能性中使用的其他字段的覆盖索引会有所帮助。我会尝试有以下索引。

Table                      Index
nms_section_region_banner  ( banner_id, region_id)  -- and in this specific order
aw_rbslider_slide_region   ( region_id, region_type, region_code )
aw_rbslider_slide_banner   ( banner_id, slide_id)
aw_rbslider_slide slide    ( id, status, display_from, display_to )
aw_rbslider_slide_store    ( slide_id, store_id )

最后,您的 ORDER BY 子句通过执行 FIELD() 函数与单独命名字段列与数字。从区域表中获得明确的字段名称更加明确和可读

于 2021-08-12T12:42:17.390 回答