【问题标题】:Not able to force index on mysql index无法在 mysql 索引上强制索引
【发布时间】:2018-05-23 02:22:20
【问题描述】:

我正在尝试优化查询,但解释查询给出 mysql 没有使用任何索引。

这是我的查询:

explain
 SELECT t1.* 

    FROM crypto_screener.prices as t1 FORCE INDEX (PRIMARY)

    where t1.id = (
      select t2.id
      from (select *
              from
              crypto_screener.prices FORCE INDEX (allfilters)
              where date > '2017-12-07'
              ) as t2
      where t2.symbol = t1.symbol
      order by t2.id desc
      limit 1
      )
;

这是show index from prices;

Table   Non_unique  Key_name    Seq_in_index    Column_name Collation   Cardinality Sub_part    Packed  Null    Index_type  Comment Index_comment
prices  0   PRIMARY 1   id  A   57718   NULL    NULL        BTREE       
prices  0   priceid 1   id  A   57718   NULL    NULL        BTREE       
prices  1   pricefilters    1   symbol  A   369 NULL    NULL    YES BTREE       
prices  1   pricefilters    2   date    A   57718   NULL    NULL    YES BTREE       
prices  1   datefilters 1   date    A   506 NULL    NULL    YES BTREE       
prices  1   symbolfilters   1   symbol  A   421 NULL    NULL    YES BTREE       
prices  1   allfilters  1   id  A   57718   NULL    NULL        BTREE       
prices  1   allfilters  2   symbol  A   57718   NULL    NULL    YES BTREE       
prices  1   allfilters  3   date    A   57718   NULL    NULL    YES BTREE       

查询现在不会以表内的数据量运行。我该如何优化它?

【问题讨论】:

  • 你不能在这里使用allfilters(因为它的索引超过 3 列并且日期不是索引中的第一列,所以基本上这个索引是无用的,因为你已经在id) 你能用datefilters吗?
  • @RolandStarke 是的,日期过滤器适用于 t2
  • 太棒了。是否足以提高性能?我无法理解此查询选择的内容。知道会很有趣。
  • @RolandStarke 表格价格有 t 个日期的 n 个符号的价格。查询为每个交易品种选择最近的行,其中包含最后的价格(最高 id)。使用日期过滤器,运行查询还不够。
  • 这适用于子查询 t2。 @O.Jones 我在上面的评论中解释了

标签: mysql query-optimization greatest-n-per-group


【解决方案1】:

对于特定日期范围内的每个不同的 symbol 值,您似乎想要具有最高 id 值的行。

您可以这样做。首先,使用子查询获取 symbol, id 值列表,其中显示每个符号的最高 id 值,用于具有所需日期的表子集。

                 SELECT symbol, MAX(id) id
                   FROM prices
                  WHERE date >  '2017-12-07'
                  GROUP BY symbol

可以通过date, symbol, id 上的复合索引优化此子查询。为什么?它将索引随机访问到第一个符合条件的日期,然后依次扫描它以查找符号和 id 的不同值。

您可以测试该子查询。确保它为您提供合理的结果。

然后在主查询中使用它,如下所示:

 SELECT t1.*
   FROM prices t1
   JOIN (
                 SELECT symbol, MAX(id) id
                   FROM prices
                  WHERE date >  '2017-12-07'
                  GROUP BY symbol
        ) t2 ON t1.id = t2.id AND t1.symbol = t2.symbol

现在,由于您的 id 值都是唯一的,您可以通过省略 AND t1.symbol = t2.symbol 来简化 ON 条件。

这应该在适当的复合索引下运行得非常快。

专业提示 1:不要仅仅为了衡量而创建额外的索引。确保他们在那里帮助您运行一些需要运行的查询。

专业提示 2date > '2017-12-07' 排除您指定日期午夜的行,但会获取该日期午夜之后的所有行。如果date 列的数据类型是DATETIME,则使用> 可能不正确。如果数据类型为DATE,则您的过滤器与date >= '2017-12-08' 的含义相同。

专业提示 3:试图强制 MySQL 的查询计划器使用某些索引通常会适得其反。更好的是确保您拥有正确的索引。

【讨论】:

  • 感谢您的回答。我在这个问题上挣扎了一段时间。非常令人印象深刻和优雅的解决方案。恭喜,我印象深刻。
猜你喜欢
  • 1970-01-01
  • 2011-06-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多