优化MySQL查询索引(交易滴答数据数据库)
我的MySQL数据库有超过3.5亿行,而且还在增长。现在它的大小是32GB。我正在使用SSD和大量RAM,但想寻求建议,以确保我使用了适当的索引优化MySQL查询索引(交易滴答数据数据库),mysql,optimization,indexing,create-table,Mysql,Optimization,Indexing,Create Table,我的MySQL数据库有超过3.5亿行,而且还在增长。现在它的大小是32GB。我正在使用SSD和大量RAM,但想寻求建议,以确保我使用了适当的索引 CREATE TABLE `qcollector` ( `key` bigint(20) NOT NULL AUTO_INCREMENT, `instrument` char(4) DEFAULT NULL, `datetime` datetime DEFAULT NULL, `last` double DEFAULT NULL,
CREATE TABLE `qcollector` (
`key` bigint(20) NOT NULL AUTO_INCREMENT,
`instrument` char(4) DEFAULT NULL,
`datetime` datetime DEFAULT NULL,
`last` double DEFAULT NULL,
`lastsize` int(10) DEFAULT NULL,
`totvol` int(10) DEFAULT NULL,
`bid` double DEFAULT NULL,
`ask` double DEFAULT NULL,
PRIMARY KEY (`key`),
KEY `datetime_index` (`datetime`)
) ENGINE=InnoDB;
show index from qcollector;
+------------+------------+----------------+--------------+-------------+-----------+-- -----------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+------------+------------+----------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| qcollector | 0 | PRIMARY | 1 | key | A | 378866659 | NULL | NULL | | BTREE | | |
| qcollector | 1 | datetime_index | 1 | datetime | A | 63144443 | NULL | NULL | YES | BTREE | | |
+------------+------------+----------------+--------------+-------------+-----------+------ -------+----------+--------+------+------------+---------+---------------+
2 rows in set (0.03 sec)
select * from qcollector order by datetime desc limit 1;
+-----------+------------+---------------------+---------+----------+---------+---------+--------+
| key | instrument | datetime | last | lastsize | totvol | bid | ask |
+-----------+------------+---------------------+---------+----------+---------+---------+--------+
| 389054487 | ES | 2012-06-29 15:14:59 | 1358.25 | 2 | 2484771 | 1358.25 | 1358.5 |
+-----------+------------+---------------------+---------+----------+---------+---------+--------+
1 row in set (0.09 sec)
典型的查询速度较慢(全表扫描,此查询需要3-4分钟):
在列上使用
date
和time
函数时,索引无法有效使用。您还可以将日期和时间存储在单独的列中,并对这些列进行索引,尽管这会占用更多的存储空间
您还可以考虑添加多列索引。关于
(仪器,日期时间)
的索引可能会对您有所帮助。您可以考虑以下几点:
- 覆盖索引(即,包含查询中引用的所有列的索引)可能会有所帮助。这样的索引将需要更多的磁盘(SSD?)空间,但它将消除MySQL访问数据页以查找不在索引中的列的值的必要性
或在qcollector上(日期时间、仪器、最后尺寸)
在qcollector上(仪器、日期时间、最后大小)
- 您真的需要从计数中排除
为空值的行吗?您能返回所有行的计数吗?如果您可以返回lastsize
或COUNT(1)
,则查询不需要引用SUM(1)
列,因此索引中不需要它来将其作为覆盖索引lastsize
表达式等价于COUNT(lastsize)
SUM(如果(lastsize为NULL,0,1))
- 当datetime范围只有NULL
值时,是否需要返回日期,或者是否可以排除所有具有NULLlastsize
值的行?也就是说,可以包含一个谓词,如lastsize
且lastsize不为空
我认为最大的问题是
TIME(datetime)
表达式上的谓词不可搜索。也就是说,MySQL不会对这些内容使用索引范围扫描操作。裸datetime
列上的谓词是sargable。。。这就是解释将datetime_索引显示为可能的键的原因
另一个大问题是,查询对派生表达式执行groupby
和orderby
操作,这将要求MySQL生成一个中间结果集(作为临时MyISAM表),然后处理该结果集。当有很多行要处理时,这可能是一项繁重的工作
至于表更改,我将考虑使用单独的日期和时间列,并使用时间戳数据类型代替DATETIME(如果您需要将日期和时间一起存储)。我将重写查询以引用裸日期和裸时间列,并考虑添加覆盖索引,该索引包含重写查询中引用的所有列,其中前行列是具有最高基数的列(并且在查询中具有最有选择性的谓词)。
大多数查询使用介于“yyyy-mm-dd hh:mm:ss”和“yyy-mm-dd hh:mm:ss”之间的datetime(只需一天或两天),因此我发现最好使用一列作为datetime,而不是两个单独的列。但有些查询(如上文所述)跨越数月或数年,我每天只需要包含特定的时间(hh:mm:ss)。只有不到10个“工具”,我的理解是,索引在这种情况下不会有帮助。如果您希望查询速度快,跨越数年,但每天只选择几次,则需要对时间进行索引。不幸的是,在MySQL中,唯一的方法就是创建一个新的列,因为它是。有趣的是(或者不太有趣…)我一开始使用两列作为日期/时间,但后来觉得效率很低,所以将它们组合起来。@user1530260:我们通常希望日期和时间放在一列中,当我们想要从连续的日期时间范围中检索行时,例如,其中datetime>='2012-07-14 08:00:00'和datetime<'2012-07-14 17:00:00'
。在您的例子中,您将分别处理日期和时间部分,因此可能需要使用单独的列。您在一整段时间内都在检索相同的小时间窗口。对于您的查询,您的索引应该同时包含这两列。如果我添加了一个覆盖索引(比如datetime、lastsize)[或新建议的结构],但查询没有使用其中一列,那么该索引还会被使用吗?或者在这种情况下我需要两个单独的索引吗?关于使用COUNT,我通常使用SUM,通常在特定的时间内使用range@user1530260:您需要一个包含所有列的索引。单独列上的索引对查询没有帮助。(它们可能对其他查询有用。)但对于您的查询,您需要一个索引。
explain select date(datetime), count(lastsize) from qcollector where instrument = 'ES' and datetime > '2011-01-01' and time(datetime) between '15:16:00' and '15:29:00' group by date(datetime) order by date(datetime) desc;
+------+-------------+------------+------+----------------+------+---------+------+-----------+----------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+------------+------+----------------+------+---------+------+-----------+----------------------------------------------+
| 1 | SIMPLE | qcollector | ALL | datetime_index | NULL | NULL | NULL | 378866659 | Using where; Using temporary; Using filesort |
+------+-------------+------------+------+----------------+------+---------+------+-----------+----------------------------------------------+