无法强制索引mysql索引

时间:2017-12-08 19:40:48

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

我正在尝试优化查询,但解释查询表明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       

现在,查询不会随着表中的数据量而运行。我该如何优化呢?

1 个答案:

答案 0 :(得分:1)

您似乎希望特定日期范围内每个不同id值的symbol值最高的行。

这是你怎么做的。首先,使用子查询获取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值都是唯一的,因此您可以省略ON来简化AND t1.symbol = t2.symbol条件。

这应该通过适当的复合指数确实非常快速地运行。

专业提示1 :不要为了衡量标准而创建额外的索引。确保它们可以帮助您运行一些查询。

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

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