所以我有一张包含大量数字数据的表:http://sqlfiddle.com/#!9/dfdb35/4/0
目前有60M行。
我需要查询此数据以获取特定date_added
和name
的最近行,上面的示例包含我用于此的查询(我使用>= 'targetdate'
和{ {1}}得到最近的。)
我的问题是这个数据没有按日期排序,所以当返回结果时我需要包含LIMIT 1
(或者它不返回正确的行)。目前,在60M行上执行此操作需要90秒才能运行,因为此ORDER BY date_added
条件。
我有什么方法可以进一步优化这个吗?我已将ORDER BY
和date_added
列编入索引,因此我不确定还能做些什么。我考虑创建一个新表,其数据按name
顺序重新排序,但这不实用,因为需要定期添加旧数据的新条目。
我已将数值数据存储为十进制,因为它可能非常小(例如date_added
),但它也可能非常大(例如0.0000243
)或甚至两者(例如{{ 1}})。也许以不同的方式存储这些数据会更有效率?有任何想法吗?我已经订购了这本书12345678
继续自己研究这个,但这不会在一段时间内烦人地到来,而且这个表格增长得相当快,所以问题正在恶化(每天增加约30万行)。
12345678.0000243
的输出:
High Performance MySQL
答案 0 :(得分:0)
在名称和日期上添加复合索引。上面的查询将在不使用filesort的情况下运行。
查询的另一种方式:
SELECT date_added, data_1, data_2, data_3, data_4, data_5, data_6, data_7, data_8, data_9
FROM numeric_data
WHERE date_added =
(select min(date_added) from numeric_data where date_added >= '2018-05-03 11:00:00' and name = 'aaa')
and name = 'aaa'
limit 1;
答案 1 :(得分:-1)
您可以使用范围分区:
https://dev.mysql.com/doc/refman/5.7/en/partitioning-range.html
您需要定义分区,具体取决于您拥有的日期范围。
CREATE TABLE `numeric_data` (
`id` int(255) NOT NULL AUTO_INCREMENT,
`date_added` datetime NOT NULL,
`name` varchar(8) COLLATE utf8mb4_unicode_ci NOT NULL,
`data_1` decimal(30,17) NOT NULL,
`data_2` decimal(30,17) NOT NULL,
`data_3` decimal(30,17) NOT NULL,
`data_4` decimal(30,17) NOT NULL,
`data_5` decimal(30,17) NOT NULL,
`data_6` decimal(30,17) NOT NULL,
`data_7` decimal(30,17) NOT NULL,
`data_8` decimal(30,17) NOT NULL,
`data_9` decimal(30,17) NOT NULL,
PRIMARY KEY (`id`),
KEY `date_added` (`date_added`),
KEY `name` (`name`)
) ENGINE=InnoDB AUTO_INCREMENT=60000000 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
PARTITION BY RANGE( TO_DAYS(date_added) ) (
PARTITION p1 VALUES LESS THAN (TO_DAYS('2018-01-01')),
PARTITION p2 VALUES LESS THAN (TO_DAYS('2018-02-01')),
PARTITION p3 VALUES LESS THAN (TO_DAYS('2018-03-01')),
PARTITION p4 VALUES LESS THAN (TO_DAYS('2018-04-01')),
PARTITION future VALUES LESS THAN MAXVALUE
);
以下查询仅使用分区" future" :
SELECT date_added, data_1, data_2, data_3, data_4, data_5, data_6, data_7, data_8, data_9
FROM numeric_data
WHERE date_added >= '2018-05-03 11:00:00'
AND name = 'aaa'
ORDER BY date_added LIMIT 1