Join 和 OrderBy 语句非常慢,77 秒,尽管有索引

问题描述 投票:0回答:1

尽管在使用

join
order by
时都有索引,但我在 MySQL 方面遇到了性能问题。该查询当前需要 77 秒 才能完成。

查询的目的是按字母顺序对表进行排序

背景

我有一个 MySQL 数据库,其中包含两个 InnoDB 表。

  • report_urls
    ;和
  • urls

每个表包含 500,000 条记录。

report_urls
url
之间存在一对一的关系。而
url
report_urls
之间存在一对多关系。

表格具有以下结构:

  • report_urls
    • id
      (主键、char36、UUID、索引)

    • url_id
      (char36、UUID、索引)

  • urls
    • id
      (主键、char36、UUID、索引)

    • title
      (varchar 255,已索引)

我需要连接这些表,并按

title
列的字母顺序对连接结果进行排序。

查询

我正在使用 Laravel 和 Eloquent ORM,但生成的 SQL 语句是:

select
  *
from
  `report_urls`
  inner join `urls` as `urls_title_sort` on `report_urls`.`url_id` = `urls_title_sort`.`id`
where
  `report_id` = '8f6598f0-34d0-48b0-be8b-41c1b8f61ffd'
order by
  `urls_title_sort`.`title` asc
limit
  11 offset 0

MySQL解释

使用

EXPLAIN
命令运行上述查询会输出以下内容:

id 选择类型 桌子 分区 类型 可能的键 key_len 参考 过滤 额外
1 简单 报告网址 参考 report_urls_url_id_foreign、report_urls_report_id_created_at_index report_urls_report_id_created_at_index 144 常量 235931 100.00 临时使用;使用文件排序
1 简单 url_标题_排序 eq_ref 小学 小学 144 数据库.report_urls.url_id 1 100.00

显示创建

SHOW CREATE TABLE report_urls;
的输出如下:

CREATE TABLE `report_urls` (
  `id` char(36) COLLATE utf8mb4_unicode_ci NOT NULL,
  `report_id` char(36) COLLATE utf8mb4_unicode_ci NOT NULL,
  `url_id` char(36) COLLATE utf8mb4_unicode_ci NOT NULL,
  `violation_count` int unsigned NOT NULL DEFAULT '0',
  `resolved_violation_count` int unsigned NOT NULL DEFAULT '0',
  `violation_minor` int unsigned NOT NULL DEFAULT '0',
  `violation_moderate` int unsigned NOT NULL DEFAULT '0',
  `violation_serious` int unsigned NOT NULL DEFAULT '0',
  `violation_critical` int unsigned NOT NULL DEFAULT '0',
  `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  KEY `report_urls_url_id_foreign` (`url_id`),
  KEY `report_urls_report_id_created_at_index` (`report_id`,`created_at`),
  KEY `report_urls_report_id_index` (`report_id`),
  KEY `report_urls_violation_count_index` (`violation_count`),
  KEY `report_urls_resolved_violation_count_index` (`resolved_violation_count`),
  KEY `report_urls_violation_minor_index` (`violation_minor`),
  KEY `report_urls_violation_moderate_index` (`violation_moderate`),
  KEY `report_urls_violation_serious_index` (`violation_serious`),
  KEY `report_urls_violation_critical_index` (`violation_critical`),
  KEY `report_urls_created_at_index` (`created_at`),
  CONSTRAINT `report_urls_report_id_foreign` FOREIGN KEY (`report_id`) REFERENCES `reports` (`id`) ON DELETE CASCADE,
  CONSTRAINT `report_urls_url_id_foreign` FOREIGN KEY (`url_id`) REFERENCES `urls` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci

问题

我需要将这些表格连接在一起并按标题字母顺序对它们进行排序。

该查询当前需要 77 秒 才能执行。我本来希望MySQL可以使用

title
索引,但是它似乎没有使用索引。

任何人都可以建议任何性能改进吗?

mysql laravel eloquent
1个回答
0
投票

多对多关系很少需要

id
,摆脱它。 然后在report_urls上有这两个索引:

INDEX(report_id, url_id)
INDEX(url_id, report_id)

这些更改将加快使用该表的大多数查询的速度。 另请参阅:多对多

(其他列和索引可以保持不变)。

对于大型表,使用 UUID (GUID) 进行索引通常效率较低。 另请参阅:UUID

© www.soinside.com 2019 - 2024. All rights reserved.