我有这个问题,我正在进行这个查询,但是花费了太长时间,比如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 | |
+-------------+------------+---------------------+--------------+---------------------+-----------+-------------+----------+--------+------+------------+---------+
这个表有大约254809条记录,我们有更大的表和更复杂的查询,它们不需要很长时间,这是查询的解释
*************************** 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)
因此,我想知道您是否能在这些数据上看到一些不好的地方,并帮助我找到更好的方法(如果可能的话),这个查询所采用的索引是否有问题?我希望你能帮助我,谢谢。
最佳答案
感兴趣的是查询的dateFechaHora
中使用的intTimbrada
、intTimbrada
、cfdi_33
、RFC_usario
和WHERE
列。idx_compuesto4
总体上看起来不错。但也试着包括dateFechaHora
。
假设统计数据是最新的(一定要运行ANALYZE TABLE tbl_factura;
),那么索引列表中各个列上的索引告诉我们,dateFechaHora
有(大约)232534个不同的值。对于intTimbrada
、intTimbrada
和cfdi_33
来说,每个都是5。对于RFC_usario
有1875个不同的值。
进一步假设,每列的所有值或多或少都是“均匀分布的”(即对于列x
,表中有n个不同的值,x
引起的所有分区都具有相似的基数),intTimbrada
,intTimbrada
和cfdi_33
不是很有选择性的。所以,如果我们把它们包含在复合索引中,它们应该排在最后。
对于dateFechaHora
来说,这并不容易,因为查询需要一个范围。但是,升序索引可以帮助快速将记录集划分为那些值低于范围最小值的记录和那些值高于范围最小值的记录。看着你的查询,我注意到,你想要发票(我猜那是那张表的内容?)上个月到期。其他的猜测是,这是通常的情况(随着时间的推移,月份“滚动”),你有很多发票到期,但在未来相对较少。也就是说,到期日的数目大于范围的最大值远小于它们的数量小于其最小值。换言之,将这些发票的到期日除以大于该范围的最小值,我们可以快速从索引中获得,并过滤掉到期日大于最大值的几个,这并不是一个太糟糕的方法。
但我对dateFechaHora
有点问题。我注意到,idx_dateFechaHora
的基数等于PRIMARY
的基数。所以我想dateFechaHora
是一个datetime
和dateFechaHora
不同,即使是同一天到期的发票。这让我有点头疼,在不同的月份232534会是什么样子,所以我有点不确定dateFechaHora
和RFC_usario
的顺序。我猜,你的用户可能更少(RFC_usario
是用户,对吧?),而不是你做生意的几个月。所以我想应该先去。其次,由于它的选择性比其他的好得多,其次才是其他的。
CREATE INDEX idx_compuesto5
ON (dateFechaHora,
RFC_usuario,
intTimbrada,
intCancelada,
cfdi_33);
如果更好,您还可以尝试交换
dateFechaHora
和RFC_usario
的顺序。正如我上面所说的,我对此不太确定。包括相对“差”的列
dateFechaHora
、RFC_usuario
和intTimbrada
都有使索引变大的缺点。也就是说,它们可以在记忆中的索引拟合(很大程度上)和相反的索引拟合之间产生差异。因此,如果没有它们,磁盘IO的整体性能可能会降低,这当然更好。如果真是这样的话,也许你想把他们赶出去。当然这可能都是错的,因为我对数据一无所知。例如,
intCancelada
的记录可能很少。这可以使cfdi_33
非常好。如果MySQL的优化器可以在这个级别上运行。我不知道。你也应该考虑一下。