MariaDB 创建的视图花费的时间太长
MariaDB Created view takes too long
我有问题。我有一个 table,里面有 600 万条记录。每条记录都有一个日期时间列,对于我的代码,我需要按升序排列的最新 16 条记录。直接从原始 table 查询出来花费的时间太长,因此我使用以下查询创建了一个视图:
SELECT openTime, high, low, a, b, c, d, e FROM Candlestick WHERE market = 'USDT' AND coin = 'ETH' AND period = '5m' ORDER BY openTime DESC LIMIT 16
这意味着该视图仅包含 16 条记录。然后在我的代码中,我将视图与以下查询一起使用:
SELECT high, low, a, b, c, d, e FROM vwCI_USDT_ETH_5m ORDER BY openTime ASC
此查询获取所有(16 条记录)记录并将其按升序排列,但即使对于这 16 行,查询也需要大约 25 秒,如下图所示:
有没有办法加快这个 select 查询?
更新
我按照@The Impaler 告诉我的那样在烛台 table 上创建了一个索引,现在我在没有视图的情况下使用以下查询:
SELECT a.high, a.low, a.a, a.b, a.c, a.d, a.e FROM (SELECT openTime, high, low, a, b, c, d, e FROM Candlestick WHERE market = 'USDT' AND coin = 'ETH' AND period = '5m' ORDER BY openTime DESC LIMIT 16 ) AS a ORDER BY a.openTime ASC
这是我现在所有的索引:
但是仍然在索引之后,这个查询大约需要 20 - 25 秒。我可以做些什么来改进它?
show create table Candlestick;
的结果:
CREATE TABLE `Candlestick` (
`dateTimeChanged` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
`openTime` bigint(20) NOT NULL,
`closeTime` bigint(20) NOT NULL,
`market` varchar(10) NOT NULL,
`coin` varchar(10) NOT NULL,
`period` varchar(10) NOT NULL,
`open` decimal(14,6) NOT NULL DEFAULT 0.000000,
`high` decimal(14,6) NOT NULL DEFAULT 0.000000,
`low` decimal(14,6) NOT NULL DEFAULT 0.000000,
`close` decimal(14,6) NOT NULL DEFAULT 0.000000,
`volume` decimal(20,8) NOT NULL DEFAULT 0.00000000,
`a` decimal(6,3) NOT NULL DEFAULT 0.000,
`b` decimal(3,0) NOT NULL DEFAULT 0,
`c` decimal(3,0) NOT NULL DEFAULT 0,
`d` decimal(3,0) NOT NULL DEFAULT 0,
`e` varchar(1) NOT NULL DEFAULT '0',
`ma5` decimal(16,8) NOT NULL DEFAULT 0.00000000,
`ema5` decimal(16,8) NOT NULL DEFAULT 0.00000000,
`ema10` decimal(16,8) NOT NULL DEFAULT 0.00000000,
`ema12` decimal(16,8) NOT NULL DEFAULT 0.00000000,
`ema20` decimal(16,8) NOT NULL DEFAULT 0.00000000,
`ema26` decimal(16,8) NOT NULL DEFAULT 0.00000000,
`ema50` decimal(16,8) NOT NULL DEFAULT 0.00000000,
`ema55` decimal(16,8) NOT NULL DEFAULT 0.00000000,
`ema100` decimal(16,8) NOT NULL DEFAULT 0.00000000,
`ema200` decimal(16,8) NOT NULL DEFAULT 0.00000000,
`rsi14AvgGain` decimal(16,8) NOT NULL DEFAULT 0.00000000,
`rsi14AvgLoss` decimal(16,8) NOT NULL DEFAULT 0.00000000,
`rsi14` decimal(16,8) NOT NULL DEFAULT 0.00000000,
`macd` decimal(16,8) NOT NULL DEFAULT 0.00000000,
`signal` decimal(16,8) NOT NULL DEFAULT 0.00000000,
`bbLower` decimal(16,8) NOT NULL DEFAULT 0.00000000,
`bbMiddle` decimal(16,8) NOT NULL DEFAULT 0.00000000,
`bbUpper` decimal(16,8) NOT NULL DEFAULT 0.00000000,
`dmiDIPositive` decimal(16,8) NOT NULL DEFAULT 0.00000000,
`dmiDINegative` decimal(16,8) NOT NULL DEFAULT 0.00000000,
`dmiADX` decimal(16,8) NOT NULL DEFAULT 0.00000000,
PRIMARY KEY (`openTime`,`market`,`coin`,`period`) USING BTREE,
KEY `OpenTime` (`openTime`) USING BTREE,
KEY `MarketCoinPeriod` (`market`,`coin`,`period`) USING BTREE,
KEY `ix1` (`market`,`coin`,`period`,`openTime`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
查询很简单。您不需要视图,但需要一个好的索引。
将提高该查询性能的索引是:
create index ix1 on Candlestick (market, coin, period, openTime);
即使在查询视图时也是如此。仍然是查询table源table,获取所有行,按照openTime降序排序,然后才选择前16行。
之后,您将按打开时间的升序对选定的 16 位数字进行排序。
我同意@The Impaler。您可能需要一个适当的索引 table.
覆盖索引可能有所帮助。
这是基于以下评论的最终建议索引:
create index ix3 on Candlestick (market, coin, period, openTime DESC, high, low, a, b, c, d, e);
这里是测试用例(fiddle)中用到的所有SQL:
Working test case for MariaDB and generated sample data
以下内容基于对实际 create table
语句的猜测,但有助于讨论一些可能的索引问题。
这是包含当前建议索引的计划和一些示例数据:
这是索引的 descending
版本的计划:
create index ix2 on Candlestick (market, coin, period, openTime DESC);
这是建议的覆盖索引:
create index ix3 on Candlestick (market, coin, period, openTime DESC, high, low, a, b, c, d, e);
与您的实际 table 以及之前的 ix1
索引:
现在使用新的建议索引(openTime DESC
顺序):
更新:MariaDB 似乎支持降序索引语法,但可能不完全支持该功能。在较新版本的 Maria(例如 10.5)中,新索引 (ix3
) 未用于此测试用例。
我们可以 force
索引,如果发现有帮助的话:
SELECT a.high, a.low, a.a, a.b, a.c, a.d, a.e
FROM (
SELECT openTime, high, low, a, b, c, d, e
FROM Candlestick FORCE INDEX (ix3)
WHERE market = 'USDT' AND coin = 'ETH' AND period = '5m'
ORDER BY openTime DESC
LIMIT 16
) AS a
ORDER BY a.openTime ASC
;
如果我们在添加索引后查看 table,我们会注意到 DESC
项被忽略:
KEY `ix3` (`market`,`coin`,`period`,`openTime`,`high`,`low`,`a`,`b`,`c`,`d`,`e`)
我有问题。我有一个 table,里面有 600 万条记录。每条记录都有一个日期时间列,对于我的代码,我需要按升序排列的最新 16 条记录。直接从原始 table 查询出来花费的时间太长,因此我使用以下查询创建了一个视图:
SELECT openTime, high, low, a, b, c, d, e FROM Candlestick WHERE market = 'USDT' AND coin = 'ETH' AND period = '5m' ORDER BY openTime DESC LIMIT 16
这意味着该视图仅包含 16 条记录。然后在我的代码中,我将视图与以下查询一起使用:
SELECT high, low, a, b, c, d, e FROM vwCI_USDT_ETH_5m ORDER BY openTime ASC
此查询获取所有(16 条记录)记录并将其按升序排列,但即使对于这 16 行,查询也需要大约 25 秒,如下图所示:
更新
我按照@The Impaler 告诉我的那样在烛台 table 上创建了一个索引,现在我在没有视图的情况下使用以下查询:
SELECT a.high, a.low, a.a, a.b, a.c, a.d, a.e FROM (SELECT openTime, high, low, a, b, c, d, e FROM Candlestick WHERE market = 'USDT' AND coin = 'ETH' AND period = '5m' ORDER BY openTime DESC LIMIT 16 ) AS a ORDER BY a.openTime ASC
这是我现在所有的索引:
show create table Candlestick;
的结果:
CREATE TABLE `Candlestick` (
`dateTimeChanged` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
`openTime` bigint(20) NOT NULL,
`closeTime` bigint(20) NOT NULL,
`market` varchar(10) NOT NULL,
`coin` varchar(10) NOT NULL,
`period` varchar(10) NOT NULL,
`open` decimal(14,6) NOT NULL DEFAULT 0.000000,
`high` decimal(14,6) NOT NULL DEFAULT 0.000000,
`low` decimal(14,6) NOT NULL DEFAULT 0.000000,
`close` decimal(14,6) NOT NULL DEFAULT 0.000000,
`volume` decimal(20,8) NOT NULL DEFAULT 0.00000000,
`a` decimal(6,3) NOT NULL DEFAULT 0.000,
`b` decimal(3,0) NOT NULL DEFAULT 0,
`c` decimal(3,0) NOT NULL DEFAULT 0,
`d` decimal(3,0) NOT NULL DEFAULT 0,
`e` varchar(1) NOT NULL DEFAULT '0',
`ma5` decimal(16,8) NOT NULL DEFAULT 0.00000000,
`ema5` decimal(16,8) NOT NULL DEFAULT 0.00000000,
`ema10` decimal(16,8) NOT NULL DEFAULT 0.00000000,
`ema12` decimal(16,8) NOT NULL DEFAULT 0.00000000,
`ema20` decimal(16,8) NOT NULL DEFAULT 0.00000000,
`ema26` decimal(16,8) NOT NULL DEFAULT 0.00000000,
`ema50` decimal(16,8) NOT NULL DEFAULT 0.00000000,
`ema55` decimal(16,8) NOT NULL DEFAULT 0.00000000,
`ema100` decimal(16,8) NOT NULL DEFAULT 0.00000000,
`ema200` decimal(16,8) NOT NULL DEFAULT 0.00000000,
`rsi14AvgGain` decimal(16,8) NOT NULL DEFAULT 0.00000000,
`rsi14AvgLoss` decimal(16,8) NOT NULL DEFAULT 0.00000000,
`rsi14` decimal(16,8) NOT NULL DEFAULT 0.00000000,
`macd` decimal(16,8) NOT NULL DEFAULT 0.00000000,
`signal` decimal(16,8) NOT NULL DEFAULT 0.00000000,
`bbLower` decimal(16,8) NOT NULL DEFAULT 0.00000000,
`bbMiddle` decimal(16,8) NOT NULL DEFAULT 0.00000000,
`bbUpper` decimal(16,8) NOT NULL DEFAULT 0.00000000,
`dmiDIPositive` decimal(16,8) NOT NULL DEFAULT 0.00000000,
`dmiDINegative` decimal(16,8) NOT NULL DEFAULT 0.00000000,
`dmiADX` decimal(16,8) NOT NULL DEFAULT 0.00000000,
PRIMARY KEY (`openTime`,`market`,`coin`,`period`) USING BTREE,
KEY `OpenTime` (`openTime`) USING BTREE,
KEY `MarketCoinPeriod` (`market`,`coin`,`period`) USING BTREE,
KEY `ix1` (`market`,`coin`,`period`,`openTime`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
查询很简单。您不需要视图,但需要一个好的索引。
将提高该查询性能的索引是:
create index ix1 on Candlestick (market, coin, period, openTime);
即使在查询视图时也是如此。仍然是查询table源table,获取所有行,按照openTime降序排序,然后才选择前16行。
之后,您将按打开时间的升序对选定的 16 位数字进行排序。
我同意@The Impaler。您可能需要一个适当的索引 table.
覆盖索引可能有所帮助。
这是基于以下评论的最终建议索引:
create index ix3 on Candlestick (market, coin, period, openTime DESC, high, low, a, b, c, d, e);
这里是测试用例(fiddle)中用到的所有SQL:
Working test case for MariaDB and generated sample data
以下内容基于对实际 create table
语句的猜测,但有助于讨论一些可能的索引问题。
这是包含当前建议索引的计划和一些示例数据:
这是索引的 descending
版本的计划:
create index ix2 on Candlestick (market, coin, period, openTime DESC);
这是建议的覆盖索引:
create index ix3 on Candlestick (market, coin, period, openTime DESC, high, low, a, b, c, d, e);
与您的实际 table 以及之前的 ix1
索引:
现在使用新的建议索引(openTime DESC
顺序):
更新:MariaDB 似乎支持降序索引语法,但可能不完全支持该功能。在较新版本的 Maria(例如 10.5)中,新索引 (ix3
) 未用于此测试用例。
我们可以 force
索引,如果发现有帮助的话:
SELECT a.high, a.low, a.a, a.b, a.c, a.d, a.e
FROM (
SELECT openTime, high, low, a, b, c, d, e
FROM Candlestick FORCE INDEX (ix3)
WHERE market = 'USDT' AND coin = 'ETH' AND period = '5m'
ORDER BY openTime DESC
LIMIT 16
) AS a
ORDER BY a.openTime ASC
;
如果我们在添加索引后查看 table,我们会注意到 DESC
项被忽略:
KEY `ix3` (`market`,`coin`,`period`,`openTime`,`high`,`low`,`a`,`b`,`c`,`d`,`e`)