0

所以我有一个包含大量数字数据的表:http ://sqlfiddle.com/#!9/dfdb35/4/0

目前有 60M 行。

我需要查询这些数据以获取特定date_added和的最接近的行name,上面的示例有我为此使用的查询(我使用>= 'targetdate'LIMIT 1获得最接近的)。

我的问题是这些数据不是按日期排序的,所以在返回结果时我需要包含ORDER BY date_added(或者它不返回正确的行)。由于这种情况,目前在 60M 行上执行此操作需要 90 秒才能运行ORDER BY

有什么方法可以进一步优化吗?我已经索引了date_addedandname列,所以我不确定还能做什么。我考虑创建一个按date_added顺序重新排序数据的新表,但这不切实际,因为需要定期添加旧数据的新条目。

我已将数字数据存储为十进制,因为它可能非常小(例如0.0000243),但它也可能非常大(例如12345678)或两者兼而有之(例如12345678.0000243)。也许以不同的方式存储这些数据会更有效?有任何想法吗?我已经命令这本书High Performance MySQL自己继续研究这个问题,但这在一段时间内不会令人讨厌,而且这个表增长得相当快,所以问题正在恶化(每天增加大约 300k 行)。

的输出EXPLAIN

id: 1
select_type: SIMPLE
table: numeric_data
partitions: NULL
type: range
possible_keys: date_added,name
key: date_added
key_len: 5
ref: NULL
rows: 29222232
filtered: 0.16
Extra: Using index condition; Using where
4

2 回答 2

0

在名称和日期上添加复合索引。上面的查询将在不使用文件排序的情况下运行。

查询的另一种方法:

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;  

小提琴:http ://sqlfiddle.com/#!9/4e8d89/1 。

于 2018-05-03T17:43:51.660 回答
-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
      );

对于以下查询将仅使用分区“未来”:

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
于 2018-05-03T13:17:02.373 回答