我有一个sync_log_lines
表,包含数百万条记录。
CREATE TABLE `sync_log_lines` (
`uuid` char(36) COLLATE utf8mb4_unicode_ci NOT NULL,
`sync_log_uuid` char(36) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`exception_time` timestamp NULL DEFAULT NULL,
`exception_message` mediumtext COLLATE utf8mb4_unicode_ci,
`exception_file` varchar(191) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`exception_line` int(10) unsigned DEFAULT NULL,
`failure_reason` varchar(191) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`csv_file_row_count` int(10) unsigned DEFAULT NULL,
`csv_file_row_sequence` int(10) unsigned DEFAULT NULL,
`csv_file_row_content` mediumtext COLLATE utf8mb4_unicode_ci,
`csv_file_source` varchar(191) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`created_at` timestamp NULL DEFAULT NULL,
`updated_at` timestamp NULL DEFAULT NULL,
PRIMARY KEY (`uuid`),
KEY `sync_log_lines_sync_log_uuid_index` (`sync_log_uuid`),
KEY `sync_log_lines_exception_time_index` (`exception_time`),
CONSTRAINT `sync_log_lines_sync_log_uuid_foreign` FOREIGN KEY (`sync_log_uuid`) REFERENCES `sync_logs` (`uuid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
单个“同步”操作可以将150k条记录插入此表中。 sync_log_lines
中的每个记录都是单个CSV行,无法在其专用表中插入或更新。
因此,在我下面使用的查询可能会迅速升级。
select `uuid`, `sync_log_uuid`, `exception_time`, `exception_message`, `failure_reason`, `csv_file_row_count`, `csv_file_row_sequence`, `csv_file_row_content`
from `sync_log_lines`
where `sync_log_uuid` = '56b0a3b1-dab4-4343-9f9b-a2a8f075c21a'
order by `exception_time` desc
limit 100 offset 6000;
总共有约15万条记录,其中sync_log_uuid
= 56b0a3b1-dab4-4343-9f9b-a2a8f075c21a
。如果没有order by
,则需要几毫秒的时间才能给我第一条100
记录。
如上所示,当我添加order by
时,它会变慢到30-45秒。
我知道,我知道。我做了一项研究,我完全理解:
当我在不使用ORDER BY-LIMIT 100的情况下运行查询时,它运行完美- 在前100条记录任何 100条记录
之后停止查询
但是
当我添加ORDER BY时,MySQL首先将所有记录发送到临时 表,然后对其进行排序,然后向我返回 100条正确记录
绝对有道理。在庞大的数据集上,它可以按预期工作。但是我已经达到了我不知道如何优化它的地步。我无法缩小日期(exception_time
的范围,因为该log lines
的所有UUID
均在2小时内插入-这大约是2小时。同步时间。
我的查询被用作分页的一部分,有时在某些情况下,用户必须查看此特定同步的页面 212(!)。
还有改进的空间吗?综合指数?还有吗?
答案 0 :(得分:3)
在sync_log_uuid和exception_time上都创建1个索引。
CREATE INDEX my_index ON sync_log_lines (sync_log_uuid, exception_time);
如果您不进行ORDER BY,查找MySQL的前100条记录将很快完成,因为它可以返回找到的前100条记录。
如果您要按例外时间订购,则MySQL必须读取其中sync_log_uuid ='56b0a3b1-dab4-4343-9f9b-a2a8f075c21a'的所有记录,以确定哪些记录是前100条。
答案 1 :(得分:0)
尝试使用复合索引也称为多列索引。它将提供更好的性能。如上述回答创建索引 http://www.mysqltutorial.org/mysql-index/mysql-composite-index/