【问题标题】:Simple SELECT query is slow with ~4Gb table (MariaDB)使用 ~4Gb 表 (MariaDB) 的简单 SELECT 查询很慢
【发布时间】:2021-05-08 07:58:37
【问题描述】:

我有一个名为tablename 的表,其结构如下:

 CREATE TABLE `tablename` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `user_id` bigint(20) unsigned NOT NULL,
  `type` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `data` longtext COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `created_at` timestamp NULL DEFAULT NULL,
  `updated_at` timestamp NULL DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `tablename_user_id_foreign` (`user_id`),
  CONSTRAINT `tablename_user_id_foreign` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=11271577 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; 

此表的当前大小是4.1Gb,我希望它会变得更大。

我正在运行一个相当简单的 SQL SELECT 查询,如下所示:

SELECT `type`, `data`, `created_at`
FROM `tablename`
WHERE `type` = 'PURCHASE'
ORDER BY `created_at` DESC
LIMIT 1

本质上,我们希望只返回一个(而不是更多)此数据库(PURCHASE 类型)中的最新行。此表中的大多数数据不是PURCHASE 类型。

在具有 4GB RAM 的生产数据库上,可以看到此查询需要长达 1 分 1 秒(这似乎太长了)。

SELECT `type`, `data`, `created_at`
FROM `tablename`
WHERE `type` = 'PURCHASE'
ORDER BY `created_at` DESC
LIMIT 1;
/* Affected rows: 0  Found rows: 1  Warnings: 0  Duration for 1 query: 00:01:01.8 */

在其他运行(相同的机器,相同的服务器)上,我发现它需要在 27 seconds36.48 秒之间。

如果可能的话,我希望最多能缩短几秒钟。

MariaDB 的版本是 10.3.27(在具有 4Gb RAM 和“通用 (SSD) 卷”的 *nix 虚拟云实例上运行)。这是正常的吗?可以做些什么来加快这个查询?瓶颈主要与 RAM 或磁盘速度或其他因素有关吗?

值得注意的是,很多新记录被写入/插入到同一个表中,同时这个SELECT 语句可能正在执行,所以这可能会减慢速度(等待@987654332 @ 语句可能会完成)。

【问题讨论】:

  • 想象你是数据库引擎。您会收到这样的查询,并且在您面前有一个无序的表格(想想 Excel 电子表格)。您将如何在其中搜索最新日期?你必须遍历整个表。现在想象一下,您有一个字典样式的索引,首先按type 排序,然后按created_date 排序,并且您可以查找每行所在位置的参考。现在很简单,马上去PURCHASE参加第一次约会。
  • 很好的解释,很有意义。谢谢。

标签: mysql sql mariadb


【解决方案1】:

对于这个查询:

SELECT `type`, `data`, `created_at`
FROM `tablename`
WHERE `type` = 'PURCHASE'
ORDER BY `created_at` DESC
LIMIT 1;

您希望在tablename(type, created_at desc) 上建立索引。

【讨论】:

  • 谢谢。我申请了alter table tablename add index `tablename_type_created_at desc_index`(`type`, `created_at`),运行大约需要 3 分钟。之前的 SELECT 语句现在按预期运行大约半秒(好多了!)
  • 不需要desc 部分,因为索引可以向后走。
  • 当我尝试在created_at 的末尾使用desc 运行alter table tablename 时,MariaDB 实际上给出了错误。没有就好。
  • “半秒”?我预计只有几毫秒。不过,我同意索引(有或没有DESC。)检查innodb_buffer_pool_size 的值;我会使用大约 1500M。
  • @JamesSpittal - buffer_pool 应该比 RAM 小很多。由于服务器有 4GB 的 RAM,将 buffer_pool 设置为 4.5G 会导致大量交换,这对性能非常不利。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-11-21
  • 1970-01-01
  • 2021-10-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多