如何更快地按连接表中的列进行排序?

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

我有一个包含大量产品的网站,每个产品都使用一个算法版本进行评分,列出后,会连接到下表中:

CREATE TABLE `product_score` (
  `product_id` int(10) UNSIGNED NOT NULL,
  `cohort_id` int(10) UNSIGNED NOT NULL,
  `score` float UNSIGNED NOT NULL,
  `last_updated` int(10) UNSIGNED NOT NULL DEFAULT 1709444313,
  `order` int(10) UNSIGNED NOT NULL DEFAULT 0
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

ALTER TABLE `product_score`
  ADD PRIMARY KEY (`product_id`,`cohort_id`),
  ADD KEY `score` (`score`),
  ADD KEY `order` (`order`),
  ADD KEY `product_id` (`product_id`,`cohort_id`,`order`);

大约有 20k 个产品,每个产品都有一个唯一的“顺序”(0-20000),具体取决于表示该条目所针对的算法版本的同类群组 ID。

有问题的查询示例:

SELECT product.*, user.*, additional_data.* FROM product
INNER JOIN product_score AS Score ON Score.product_id = product.product_id AND Score.cohort_id = '24') 
LEFT JOIN user ON user.user_id = product.user_id
LEFT JOIN additional_data...
ORDER BY Score.order LIMIT 20

很敏捷。然而,使用 order by 则需要 1-2 秒。

就附加索引而言,我认为没有任何改进的空间。我已经对查询运行了 EXPLAIN,并且 Product_id 键也在连接中得到了正确的利用。

我注意到,当删除左连接时,查询只需要 0.2 秒而不是 1 秒(与没有 order by 相比仍然很慢,但没有那么慢)。但是,该数据是查询所必需的,因此我不能简单地将其删除。我对 DB io 的了解也不够,无法推断它的含义或如何最好地解决它。

以下是示例查询的分析信息: Profiling information

mysql mariadb query-optimization
1个回答
0
投票

更换

 ADD KEY `product_id` (`product_id`,`cohort_id`,`order`);

INDEX(cohort_id, `order`, product_id)

如果这还不够加快速度,请重写查询以在子查询中查找 20 行,然后再查看其他列或表:

SELECT product.*, user.*, additional_data.*
    FROM ( SELECT product_id, `order`
            FROM  Score.cohort_id = '24'
            ORDER BY  Score.order
            LIMIT  20 ) AS s1
    JOIN product USING(product_id)
    LEFT JOIN user USING(user_id)
    LEFT JOIN  additional_data...
    ORDER BY  s1.order
© www.soinside.com 2019 - 2024. All rights reserved.