mysql:在具有按时间戳排序的大型表上进行非常慢的查询(尽管有索引)…

wqlqzqxt  于 2021-06-17  发布在  Mysql
关注(0)|答案(2)|浏览(266)

我有一个 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时,mysql首先将所有记录发送到临时表,然后对其排序,然后返回100条正确的记录
这绝对有道理。在巨大的数据集上,它的工作方式与预期一致。但我已经到了不知道如何优化的地步。我不能缩小日期( exception_time )因为所有 log lines 为了这个 UUID 在2小时内插入-这是大约同步时间。
我的查询用作分页的一部分,有时用户必须查看第212页(!)这个特别的同步。
还有改进的空间吗?综合指数?别的?

mbskvtky

mbskvtky1#

在sync\u log\u uuid和exception\u time上创建1个索引。

CREATE INDEX my_index ON sync_log_lines (sync_log_uuid, exception_time);

对于mysql来说,如果不按order-by,查找前100条记录很快就会完成,因为它可以返回找到的前100条记录。
如果您通过异常订购,mysql必须读取sync\u log\u uuid='56b0a3b1-dab4-4343-9f9b-a2a8f075c21a'的所有记录,以确定哪些记录是前100条记录。

lnlaulya

lnlaulya2#

尝试使用复合索引也称为多列索引。它将提供更好的性能。如上所述,回答创建索引http://www.mysqltutorial.org/mysql-index/mysql-composite-index/

相关问题