【问题标题】:Optimize MySQL count query, full info provided优化 MySQL 计数查询,提供完整信息
【发布时间】:2013-02-07 10:58:35
【问题描述】:

我的这个查询运行了 3 分钟以上。我希望优化以在几秒钟内运行:

SELECT Count(DISTINCT l.licitatii_id) c 
FROM   licitatii_ue l 
       INNER JOIN domenii_licitatii dl 
               ON l.licitatii_id = dl.licitatii_id 
                  AND dl.tip_licitatie = '2' 
       INNER JOIN domenii d 
               ON dl.domenii_id = d.domenii_id 
                  AND d.tip_domeniu = '1' 
                  AND d.status = 1 
WHERE  l.status = 1 
       AND l.data_limita >= '1357768800' 

解释显示:

*** row 1 ***
          table:  d
           type:  ref
  possible_keys:  PRIMARY,key_status_tip_domeniu,ind_v1
            key:  key_status_tip_domeniu
        key_len:  9
            ref:  const,const
           rows:  39
          Extra:  Using where; Using index
*** row 2 ***
          table:  dl
           type:  ref
  possible_keys:  PRIMARY,licitatii_id,licitatii_id_2
            key:  PRIMARY
        key_len:  5
            ref:  web1db1.d.domenii_id,const
           rows:  1882
          Extra:  Using index
*** row 3 ***
          table:  l
           type:  eq_ref
  possible_keys:  PRIMARY,data_limita
            key:  PRIMARY
        key_len:  4
            ref:  web1db1.dl.licitatii_id
           rows:  1
          Extra:  Using where

架构:

licitatii_ue

  PRIMARY KEY (`licitatii_id`),
  UNIQUE KEY `nr_ue` (`nr_ue`),
  KEY `nume` (`nume`),
  KEY `tip_licitatie` (`tip_licitatie`),
  KEY `surse_ue_id` (`surse_ue_id`),
  KEY `data_publicarii` (`data_publicarii`),
  KEY `tara_id` (`tara_id`),
  KEY `creat` (`creat`),
  KEY `data_limita` (`data_limita`),
  FULLTEXT KEY `nume_fulltext` (`nume`,`descriere`)
) ENGINE=MyISAM

/*Index Information*/
---------------------

Table         Non_unique  Key_name         Seq_in_index  Column_name      Collation  Cardinality  Sub_part  Packed  Null    Index_type  Comment  
------------  ----------  ---------------  ------------  ---------------  ---------  -----------  --------  ------  ------  ----------  ---------
licitatii_ue           0  PRIMARY                     1  licitatii_id     A               136456    (NULL)  (NULL)          BTREE                
licitatii_ue           0  nr_ue                       1  nr_ue            A               (NULL)    (NULL)  (NULL)  YES     BTREE                
licitatii_ue           1  nume                        1  nume             A                68228    (NULL)  (NULL)          BTREE                
licitatii_ue           1  tip_licitatie               1  tip_licitatie    A                   13    (NULL)  (NULL)  YES     BTREE                
licitatii_ue           1  surse_ue_id                 1  surse_ue_id      A                    1    (NULL)  (NULL)          BTREE                
licitatii_ue           1  data_publicarii             1  data_publicarii  A               136456    (NULL)  (NULL)  YES     BTREE                
licitatii_ue           1  tara_id                     1  tara_id          A                   41    (NULL)  (NULL)  YES     BTREE                
licitatii_ue           1  creat                       1  creat            A               136456    (NULL)  (NULL)  YES     BTREE                
licitatii_ue           1  data_limita                 1  data_limita      A                  770    (NULL)  (NULL)  YES     BTREE                
licitatii_ue           1  nume_fulltext               1  nume             (NULL)               1    (NULL)  (NULL)          FULLTEXT             
licitatii_ue           1  nume_fulltext               2  descriere        (NULL)               1    (NULL)  (NULL)  YES     FULLTEXT   

domenii_licitatii

  PRIMARY KEY (`domenii_id`,`tip_licitatie`,`licitatii_id`),
  KEY `licitatii_id` (`licitatii_id`,`tip_licitatie`),
  KEY `licitatii_id_2` (`licitatii_id`)
) ENGINE=InnoDB 

/*Index Information*/
---------------------

Table              Non_unique  Key_name        Seq_in_index  Column_name    Collation  Cardinality  Sub_part  Packed  Null    Index_type  Comment  
-----------------  ----------  --------------  ------------  -------------  ---------  -----------  --------  ------  ------  ----------  ---------
domenii_licitatii           0  PRIMARY                    1  domenii_id     A                   20    (NULL)  (NULL)          BTREE                
domenii_licitatii           0  PRIMARY                    2  tip_licitatie  A                  228    (NULL)  (NULL)          BTREE                
domenii_licitatii           0  PRIMARY                    3  licitatii_id   A               430634    (NULL)  (NULL)          BTREE                
domenii_licitatii           1  licitatii_id               1  licitatii_id   A               430634    (NULL)  (NULL)          BTREE                
domenii_licitatii           1  licitatii_id               2  tip_licitatie  A               430634    (NULL)  (NULL)          BTREE                
domenii_licitatii           1  licitatii_id_2             1  licitatii_id   A               430634    (NULL)  (NULL)          BTREE                

domenii

  PRIMARY KEY (`domenii_id`),
  KEY `key_status_tip_domeniu` (`status`,`tip_domeniu`),
  KEY `ind_v1` (`domenii_id`,`tip_domeniu`,`status`),
  KEY `parent_id` (`parent_id`)
) ENGINE=InnoDB 

/*Index Information*/
---------------------

Table    Non_unique  Key_name                Seq_in_index  Column_name  Collation  Cardinality  Sub_part  Packed  Null    Index_type  Comment  
-------  ----------  ----------------------  ------------  -----------  ---------  -----------  --------  ------  ------  ----------  ---------
domenii           0  PRIMARY                            1  domenii_id   A                   79    (NULL)  (NULL)          BTREE                
domenii           1  key_status_tip_domeniu             1  status       A                    4    (NULL)  (NULL)  YES     BTREE                
domenii           1  key_status_tip_domeniu             2  tip_domeniu  A                   11    (NULL)  (NULL)          BTREE                
domenii           1  ind_v1                             1  domenii_id   A                   79    (NULL)  (NULL)          BTREE                
domenii           1  ind_v1                             2  tip_domeniu  A                   79    (NULL)  (NULL)          BTREE                
domenii           1  ind_v1                             3  status       A                   79    (NULL)  (NULL)  YES     BTREE                
domenii           1  parent_id                          1  parent_id    A                   79    (NULL)  (NULL)          BTREE  

【问题讨论】:

    标签: php mysql apache query-optimization


    【解决方案1】:

    您的表确实需要复合索引。

    table             index
    licitatii         ( status, data_limita, licitatii_id )
    domenii_licitatii ( licitatii_id, tip_licitatie )
    domenii           ( domenii_id, tip_domeniu, status )
    

    您应该拥有有助于优化联接 AND where 条件的复合键。此外,正如我将它们包含在内,查询引擎可以直接从索引中找到连接的值,而不是返回到实际数据的页面。如果索引中只有一列,则查询将转到原始数据进行连接。看看它对你有什么作用。

    好的,是的,其他两个索引和您添加的第三个索引 - 没有帮助。然后我会尝试反转查询......不完全了解数据,但看起来它们是某种类型的查找类别元素。试试

    select STRAIGHT_JOIN
          Count(DISTINCT dl.licitatii_id) c
       from
          domenii d
             join domenii_licitatii dl
                on d.domenii_id = dl.domenii_id
               AND dl.tip_licitatie = '2'
                JOIN licitatii_ue L
                   on dl.licitatii_id = L.licitatii_id
                  AND L.status = 1
                  AND L.Data_Limita >= '1357768800'
       where
              d.tip_domeniu = '1'
          and d.status = 1
    

    由 Pentium10 添加

    解释显示如下:

    +---+--------+----+--------+---------------------------------------+------------------------+---+----------------------------+------+--------------------------+
    | 1 | SIMPLE | d  | ref    | PRIMARY,key_status_tip_domeniu,ind_v1 | key_status_tip_domeniu | 9 | const,const                |   39 | Using where; Using index |
    | 1 | SIMPLE | dl | ref    | PRIMARY,licitatii_id,licitatii_id_2   | PRIMARY                | 5 | web1db1.d.domenii_id,const | 1882 | Using index              |
    | 1 | SIMPLE | L  | eq_ref | PRIMARY,data_limita,i1                | PRIMARY                | 4 | web1db1.dl.licitatii_id    |    1 | Using where              |
    +---+--------+----+--------+---------------------------------------+------------------------+---+----------------------------+------+--------------------------+
    

    【讨论】:

    • 我添加了第一个索引,另一个也已经存在。它没有帮助。它根本没有被捡起。
    • @Pentium10,查看修改后的选项
    • 我已将解释添加到您的答案中。仍然只拾取主索引。重写查询背后的逻辑是什么?
    • @Pentium10,在不知道关于在什么级别/条件下有多少记录的数据的情况下,我试图强制使用一种替代方法,该方法可能在第一个表位置具有较小的记录集。这和使用 STRAIGHT_JOIN 在过去帮助许多查询覆盖优化器想要做的事情。有时有效,有时无效,但只是针对数据的另一种方法。
    【解决方案2】:

    这里我把末尾的WHERE子句移到了开头的子查询中,这样就不用过滤更多末尾INNER JOINs创建的行了,已经及时正确过滤了对于第一个INNER JOIN。这会运行 2 个查询,但应该会更快。

    SELECT Count(DISTINCT l.licitatii_id) c 
    FROM   (SELECT DISTINCT licitatii_id 
            FROM   licitatii_ue l 
            WHERE  l.status = 1 
            AND    l.data_limita >= '1357768800' 
            ) l 
           INNER JOIN domenii_licitatii dl 
                   ON l.licitatii_id = dl.licitatii_id 
                      AND dl.tip_licitatie = '2' 
           INNER JOIN domenii d 
                   ON dl.domenii_id = d.domenii_id 
                      AND d.tip_domeniu = '1' 
                      AND d.status = 1 
    

    【讨论】:

    • 这没有用,它运行了 4 分 56 秒。
    • 原始WHERE 子句是否有组合索引?看起来他们在INNER JOINs 中的其他列中。尝试在表licitatii_ue 中的l.statusl.data_limita 上创建组合索引,然后再次运行上述操作。
    猜你喜欢
    • 2011-05-22
    • 2013-04-16
    • 2020-05-21
    • 2012-10-09
    • 1970-01-01
    • 1970-01-01
    • 2013-02-14
    • 2012-07-12
    • 1970-01-01
    相关资源
    最近更新 更多