我正在尝试优化查询,但解释查询表明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
现在,查询不会随着表中的数据量而运行。我该如何优化呢?
答案 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的查询计划程序使用某些索引通常会适得其反。更好的是确保你有正确的索引。