在MySQL中优化SQL查询一个表

时间:2018-04-30 20:57:27

标签: mysql sql optimization

我有这个问题,我正在进行此查询,但是花了太长时间,比如10秒才找到95条记录

SELECT * FROM tbl_factura WHERE dateFechaHora >= '2018-04-01' AND dateFechaHora <= '2018-04-30' AND intTimbrada = 1 AND intCancelada = 0 AND cfdi_33 = 1 AND RFC_usuario = 'FRANCISCOI10'

mysql> show indexes from tbl_factura;

+-------------+------------+---------------------+--------------+---------------------+-----------+-------------+----------+--------+------+------------+---------+
| Table       | Non_unique | Key_name            | Seq_in_index | Column_name         | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |
+-------------+------------+---------------------+--------------+---------------------+-----------+-------------+----------+--------+------+------------+---------+
| tbl_factura |          0 | PRIMARY             |            1 | idFactura           | A         |      232534 |     NULL | NULL   |      | BTREE      |         |
| tbl_factura |          1 | idx_idContador      |            1 | idContador          | A         |        3875 |     NULL | NULL   |      | BTREE      |         |
| tbl_factura |          1 | idx_dateFechaHora   |            1 | dateFechaHora       | A         |      232534 |     NULL | NULL   |      | BTREE      |         |
| tbl_factura |          1 | idx_intTimbrada     |            1 | intTimbrada         | A         |           5 |     NULL | NULL   |      | BTREE      |         |
| tbl_factura |          1 | idx_intCancelada    |            1 | intCancelada        | A         |           5 |     NULL | NULL   |      | BTREE      |         |
| tbl_factura |          1 | idx_idContadorSub   |            1 | idContadorSub       | A         |         113 |     NULL | NULL   |      | BTREE      |         |
| tbl_factura |          1 | idx_intFolio        |            1 | intFolio            | A         |       21139 |     NULL | NULL   |      | BTREE      |         |
| tbl_factura |          1 | idx_formaPago       |            1 | strFormaPago        | A         |          12 |     NULL | NULL   |      | BTREE      |         |
| tbl_factura |          1 | idx_email_enviado   |            1 | email_enviado       | A         |           7 |     NULL | NULL   |      | BTREE      |         |
| tbl_factura |          1 | idx_cfdi33          |            1 | cfdi_33             | A         |           5 |     NULL | NULL   |      | BTREE      |         |
| tbl_factura |          1 | idx_intStatus       |            1 | intStatus           | A         |           5 |     NULL | NULL   |      | BTREE      |         |
| tbl_factura |          1 | idx_status          |            1 | intStatus           | A         |           5 |     NULL | NULL   |      | BTREE      |         |
| tbl_factura |          1 | idx_serie           |            1 | strSerie            | A         |           5 |     NULL | NULL   |      | BTREE      |         |
| tbl_factura |          1 | idx_rfc_usuario     |            1 | RFC_usuario         | A         |        1875 |     NULL | NULL   |      | BTREE      |         |
| tbl_factura |          1 | idx_facturaexcel    |            1 | facturaExcel        | A         |           5 |     NULL | NULL   |      | BTREE      |         |
| tbl_factura |          1 | idx_razonSocial     |            1 | CH_razon_social     | A         |       58133 |     NULL | NULL   |      | BTREE      |         |
| tbl_factura |          1 | idx_nombreComercial |            1 | CH_nombre_comercial | A         |        2397 |     NULL | NULL   |      | BTREE      |         |
| tbl_factura |          1 | idx_RFC             |            1 | CH_RFC              | A         |       38755 |     NULL | NULL   |      | BTREE      |         |
| tbl_factura |          1 | idx_compuesto1      |            1 | idFactura           | A         |      232534 |     NULL | NULL   |      | BTREE      |         |
| tbl_factura |          1 | idx_compuesto1      |            2 | idContador          | A         |      232534 |     NULL | NULL   |      | BTREE      |         |
| tbl_factura |          1 | idx_compuesto1      |            3 | cfdi_33             | A         |      232534 |     NULL | NULL   |      | BTREE      |         |
| tbl_factura |          1 | idx_compuesto2      |            1 | idContador          | A         |        2835 |     NULL | NULL   |      | BTREE      |         |
| tbl_factura |          1 | idx_compuesto2      |            2 | cfdi_33             | A         |        4471 |     NULL | NULL   |      | BTREE      |         |
| tbl_factura |          1 | idx_compuesto3      |            1 | dateFechaHora       | A         |      232534 |     NULL | NULL   |      | BTREE      |         |
| tbl_factura |          1 | idx_compuesto3      |            2 | intTimbrada         | A         |      232534 |     NULL | NULL   |      | BTREE      |         |
| tbl_factura |          1 | idx_compuesto3      |            3 | intCancelada        | A         |      232534 |     NULL | NULL   |      | BTREE      |         |
| tbl_factura |          1 | idx_compuesto3      |            4 | cfdi_33             | A         |      232534 |     NULL | NULL   |      | BTREE      |         |
| tbl_factura |          1 | idx_compuesto3      |            5 | RFC_usuario         | A         |      232534 |     NULL | NULL   |      | BTREE      |         |
| tbl_factura |          1 | idx_compuesto4      |            1 | RFC_usuario         | A         |        3633 |     NULL | NULL   |      | BTREE      |         |
| tbl_factura |          1 | idx_compuesto4      |            2 | intTimbrada         | A         |        4306 |     NULL | NULL   |      | BTREE      |         |
| tbl_factura |          1 | idx_compuesto4      |            3 | intCancelada        | A         |        6459 |     NULL | NULL   |      | BTREE      |         |
| tbl_factura |          1 | idx_compuesto4      |            4 | cfdi_33             | A         |        9301 |     NULL | NULL   |      | BTREE      |         |
| tbl_factura |          1 | idx_folio_fiscal    |            1 | strFolioFiscal      | A         |      232534 |     NULL | NULL   |      | BTREE      |         |
+-------------+------------+---------------------+--------------+---------------------+-----------+-------------+----------+--------+------+------------+---------+

这个表有大约254,809条记录,我们有更大的表,查询更复杂,它们不需要很长时间,这是查询的解释

*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: tbl_factura
         type: ref
possible_keys: idx_dateFechaHora,idx_intTimbrada,idx_intCancelada,idx_cfdi33,idx_rfc_usuario,idx_compuesto3,idx_compuesto4
          key: idx_compuesto4
      key_len: 64
          ref: const,const,const,const
         rows: 493
        Extra: Using where
1 row in set (0.45 sec)

所以我想知道你是否可以在这些数据上看到不好的东西并帮助我找到更好的方法来做到这一点,如果可能的话,这个查询所采用的索引是否有问题?我希望你能帮助我,谢谢。

1 个答案:

答案 0 :(得分:1)

感兴趣的是dateFechaHoraintTimbradaintTimbradacfdi_33RFC_usario列,因为它们在您的WHERE中使用查询。 idx_compuesto4看起来很不错。但请尝试添加dateFechaHora

假设统计数据是最近的(确保运行ANALYZE TABLE tbl_factura;),索引列表中各列的索引告诉dateFechaHora(大致)有232534个不同的值。对于intTimbradaintTimbradacfdi_33,每个人都为5。对于RFC_usario,有1875个不同的值。

进一步假设,每列的所有值都或多或少“均匀分布”(即对于列x,表中有 n 个不同的值,并且{{ {1}}具有相似的基数),xintTimbradaintTimbrada不是很有选择性。因此,如果我们将它们包含在复合索引中,它们应该是最后的。

对于cfdi_33来说,这并不容易,因为查询会询问范围。但升序索引可以帮助快速将记录集划分为那些记录,这些记录的值低于范围的最小值,并且具有比它更高的值。看着你的查询,我注意到,你想要上个月到期的发票(这就是那张表所持有的,我猜?)。其他猜测是,这是通常的情况(随着时间的推移,月份“滚动”),并且你有很多发票在过去,但将来相对较少。也就是说,大于范围最大值的截止日期数远小于它们小于其最小值的数量。换句话说,将那些发票的分区的截止日期大于范围的最小值,我们可以从索引中快速获得,并过滤掉截止日期大于最大值的少数也不是太糟糕方法

但我对dateFechaHora有点问题。我注意到,dateFechaHora的基数等于idx_dateFechaHora的基数。所以我猜PRIMARY dateFechaHora datetimedateFechaHora的差异,即使是当天发票也是如此。这让我有点头疼232534在不同月份会是什么,所以我对dateFechaHoraRFC_usario的顺序有些不确定。我猜想你的用户数量更少(RFC_usario是用户,对吧?),而不是你做生意的几个月。所以我认为dateFechaHora应该先行。然后是RFC_usario,因为它的选择性远远高于其他选择,其次是其他选择。

CREATE INDEX idx_compuesto5
             ON (dateFechaHora,
                 RFC_usuario,
                 intTimbrada,
                 intCancelada,
                 cfdi_33);

如果情况好转,您也可以尝试交换dateFechaHoraRFC_usuario的顺序。正如我上面所说,我对此并不太确定。

包括相对“不好”的列intTimbradaintCanceladacfdi_33的缺点是使索引更大。也就是说,它们可以在内存中的索引拟合(大部分)与相反的方式之间产生差异。因此,没有它们,磁盘IO可能总体上更少,这当然更好。所以,如果是这样的话,也许你想尝试将它们踢掉。

当然这可能都是错的,因为我对数据一无所知。例如,cfdi_33 = 1可能只有很少的记录。这可能会使cfdi_33非常好。如果MySQL的优化器可以在该级别上播放。我不知道。您可能也想考虑这一点。