【问题标题】:MYSQL LOW LIMIT VALUE SLOW DOWN MY QUERYMYSQL LOW LIMIT VALUE 减慢我的查询速度
【发布时间】:2017-12-02 05:04:58
【问题描述】:

当我在 MariaDB 10.1/MySQL 5.7 中执行以下查询时,结果有 849 行并在 0,016 秒内执行。

SELECT a.*
FROM bco_dav_dm.d_ttlz_cli a
WHERE FL_ATND_FNAL = 0
AND a.ID_ATND = 218
ORDER BY A.FL_CRTR,  A.DT_PRMR_ATVC_LNHA;

但是当我添加 LIMIT 子句以仅返回 1 行时,查询将在 9 秒内执行!!!为什么?

我测试过: 使用 LIMIT 1 查询在 9 秒内执行。 使用 LIMIT 2 查询在 9 秒内执行。 使用 LIMIT 3 查询在 9 秒内执行。 使用 LIMIT 4 及以上 (5,6,7,8...100, 200, 300, 400) 查询在 0,016 秒内执行!!!

我测试了好几次,结果都是一样的。

我将如何在 Web App 中使用此查询,我只需要 1 条记录我不知道为什么 LIMIT

在其他帖子中,谈到使用较高的 OFFSET 自然会减慢查询速度,但我不使用 OFFSET。

我的解释:

select_type: SIMPLE 
table:a 
type:ref    
possible_keys:ID_ATND,FL_ATND_FNAL
key:ID_ATND 
key_len:5   
ref:const   
rows:1846
Extra: Using where; Using filesort

已编辑:

我注意到当我使用 LIMIT 3 或低于我的解释更改时

select_type: SIMPLE 
table:a 
type:ref    
possible_keys:ID_ATND,FL_ATND_FNAL
key:ORDER_BY_CRTR_DT
key_len:6
ref:const   
rows:1764
Extra: Using where

索引 ORDER_BY_CRTR_DT 是我在 ORDER BY 中使用的组合索引

INDEX ORDER_BY_CRTR_DT(FL_CRTR, DT_PRMR_ATVC_LNHA);

【问题讨论】:

  • 这是有限制还是无限制的解释?
  • @NorbertvanNobelen 没有 LIMIT 和 LIMIT 时等于或大于 4。
  • 您应该使用有助于 WHERE 和 ORDER BY 的复合索引。按以下顺序使用这些列定义索引:(ID_ATND, FL_ATND_FNAL, FL_CRTR, DT_PRMR_ATVC_LNHA)。顺序很重要。
  • 当用户选择 FL_PRFLFL_GRPO_PRFL(BIT 字段)时,我有此查询的其他变体,查询更改为 SELECT a.* FROM bco_dav_dm.d_ttlz_cli a WHERE FL_ATND_FNAL = 0 AND ( a.ID_ATND = 218 OR (a.FL_CRTR = 0 AND (a.FL_PRFL & 0 OR a.FL_GRPO_PRFL & 1))) ORDER BY FL_CRTR, A.DT_PRMR_ATVC_LNHA LIMIT 1; 在这种情况下,查询执行 0.01 秒。解释是:select_type: SIMPLE table:a type:ref possible_keys: ID_ATND,FL_CRTR,FL_ATND_FNAL,ORDER_BY_CRTR_DT' key:ORDER_BY_CRTR_DT key_len:6 ref:const rows:1 Extra: Using where

标签: mysql sql dml


【解决方案1】:

基于成本的优化器对不同限制的情况略有不同,在这种情况下得到的结果是完全错误的。你会在几乎所有基于成本的数据库中更频繁地看到这种奇怪的行为。

在这种情况下,您看到差异的地方是在另一个计划中选择的索引ORDER_BY_CRTR_DTID_ATND,然后数据库使用它来估计行数。看到较少的行数,基于成本的优化器假定查询更快(简化的观点)。

有时可以帮助重建表和索引,以便它们在描述数据的直方图中都具有有关数据的最新信息。随着时间的推移,结果可能会由于插入、更新和删除而再次发生变化,从而导致计划再次降级。然而,通常通过定期重建来稳定计划。

您可以强制使用索引,结果是禁用此计划的基于成本的优化器。然而,这可能会适得其反,就像基于成本的优化器现在让你失败一样。

第二种选择是删除给你 9s 结果的索引,如果它不使用或对其他查询影响很小,这可能是一个选项。

【讨论】:

  • 当我删除 INDEX ORDER_BY_CRTR_DT 时,查询很快被返回,与 LIMIT 1 或 LIMIT 100 或 LIMIT 500 一样。但查询的第二种形式(在上面的评论中引用)受到影响。执行时间从 0.01 秒到 9 秒。
  • ORDER BY 意味着它必须遍历所有数据。使用 LIMIT 1(没有 ORDER BY),它将真正获得它可以到达的第一条记录,因此单个块数据,1 个索引块检索,匹配其他数据,返回。这可能(纯属巧合)与您在 ORDER BY 中已有的记录相同。如果您不需要 ORDER BY 来查找您要查找的数据,请避免使用它,否则您几乎会被上面的故事所困扰。
猜你喜欢
  • 2014-01-30
  • 2011-05-27
  • 2017-12-24
  • 1970-01-01
  • 2011-10-04
  • 2019-08-13
  • 1970-01-01
  • 2015-11-27
相关资源
最近更新 更多