我遇到了一些重大问题,这些问题会导致数据集变细,从而及时返回结果。我已经粘贴在此表的索引下面(我认为这足以提高速度)以及查询的逻辑。
我试过的一件事是删除" ORDER BY"在内部查询,但实际上并没有改善它的时间,以及清理我选择的一些额外的不需要的列,这改善了时间,但没有使它"足够快"。
SELECT unix_date, price FROM
(SELECT @row := @row +1 as row_num, unix_date, price
FROM (SELECT @row:=0, unix_date, price FROM
price_data WHERE created_date >= '2017-03-26 00:00:00' AND created_date
<= '2017-06-26 23:59:59' AND currency= 'USD' ORDER BY unix_date DESC)
AS p) AS d
WHERE MOD(row_num, 288) = 1;
此查询的重点只是尝试返回价格数据点的结果集(unix时间戳,价格),但将其细化为仅返回每288(或X)个数据点。这个表目前很小(总行数:198109),所以我很难理解为什么查询需要这么长时间才能返回。
以下是目前表格中的索引:
| Table | Non_unique | Key_name | Seq_in_index |
Column_name | Collation | Cardinality | Sub_part | Packed | Null |
Index_type | Comment | Index_comment |
+--------------------+------------+--------------+--------------+------
--------+-----------+-------------+----------+--------+------+---------
---+---------+---------------+
| price_data | 0 | PRIMARY | 1 |
unix_date | A | 200002 | NULL | NULL | |
BTREE | | |
| price_data | 0 | PRIMARY | 2 |
currency | A | 200002 | NULL | NULL | |
BTREE | | |
| price_data | 1 | created_date | 1 |
created_date | A | 200002 | NULL | NULL | |
BTREE | | |
| price_data | 1 | price | 1 | price
| A | 200002 | NULL | NULL | YES | BTREE |
| |
+--------------------+------------+--------------+--------------+------
--------+-----------+-------------+----------+--------+------+---------
---+---------+--
根据我的建议我添加了创建表:
CREATE TABLE `price_data` (
`created_date` datetime NOT NULL,
`unix_date` int(11) NOT NULL,
`currency` varchar(255) NOT NULL DEFAULT '',
`price` decimal(10,6) DEFAULT NULL,
PRIMARY KEY (`unix_date`,`currency`),
KEY `created_date` (`created_date`),
KEY `price` (`price`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 |
非常感谢有关如何提高此查询速度的任何建议。
编辑:问题是否与此查询的最终WHERE一致,实际上是针对&#34;假列&#34; row_num是从前面的内部查询派生的,因此它本身并没有真正的索引?因此,当WHERE正在评估它时,正常索引列的速度不是这样吗?
答案 0 :(得分:2)
将主键更改为货币unix_date。由于您具有货币的相等条件和unix_date的范围条件,因此应首先将具有相等条件的列放入。然后,unix_date和ORDER BY上的范围条件都应该使用主键顺序。
将条件应用于unix_date,而不是create_date,以使其使用主键索引。
您必须使用派生表子查询,但不必使用两个嵌套级别的子查询。
SELECT row_num, unix_date, price
FROM (
SELECT @row := @row + 1 AS row_num, unix_date, price
FROM (SELECT @row := 0) AS _init
CROSS JOIN price_data
WHERE currency = 'USD'
AND unix_date BETWEEN UNIX_TIMESTAMP('2017-03-26 00:00:00')
AND UNIX_TIMESTAMP('2017-06-26 23:59:59')
ORDER BY unix_timestamp DESC
) AS t
WHERE MOD(row_num, 288) = 1
您应该学会use EXPLAIN来帮助您分析索引使用情况。
您可能还需要我的演示文稿How to Design Indexes, Really和视频:https://www.youtube.com/watch?v=ELR7-RdU9XU
MySQL 8.0应该有窗口函数,所以有时候要在明年查找。