You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MySQL多表ORDER BY查询性能优化方案咨询

表结构与索引

table1结构

mysql> describe table1;
+---------+---------------------+------+-----+-------------------+----------------+
| Field   | Type                | Null | Key | Default           | Extra          |
+---------+---------------------+------+-----+-------------------+----------------+
| id      | bigint(20) unsigned | NO   | PRI | NULL              | auto_increment |
| field1  | varchar(255)        | NO   | UNI | NULL              |                |
| date    | timestamp           | NO   | MUL | CURRENT_TIMESTAMP |                |
| text    | varchar(10000)      | NO   |     | NULL              |                |
| flag    | tinyint(1)          | YES  |     | 0                 |                |
+---------+---------------------+------+-----+-------------------+----------------+

table1索引

mysql> show indexes from table1;
+--------+------------+--------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table  | Non_unique | Key_name           | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+--------+------------+--------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| table1 |          0 | PRIMARY            |            1 | id          | A         |     1420047 |     NULL | NULL   |      | BTREE      |         |               |
| table1 |          0 | table1_field1_unique |            1 | field1      | A         |     1420047 |     NULL | NULL   |      | BTREE      |         |               |
| table1 |          1 | table1_date_idx    |            1 | date        | A         |     1420047 |     NULL | NULL   |      | BTREE      |         |               |
+--------+------------+--------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+

table2结构

mysql> describe table2;
+------------------------+---------------------+------+-----+---------+----------------+
| Field                  | Type                | Null | Key | Default | Extra          |
+------------------------+---------------------+------+-----+---------+----------------+
| id                     | bigint(20) unsigned | NO   | PRI | NULL    | auto_increment |
| table1_id              | bigint(20) unsigned | NO   | MUL | NULL    |                |
| some1_id               | bigint(20) unsigned | YES  | MUL | NULL    |                |
| some1_name             | varchar(255)        | YES  | MUL | NULL    |                |
| some2_id               | bigint(20) unsigned | NO   | MUL | NULL    |                |
| some2_name             | varchar(255)        | NO   | MUL | NULL    |                |
| some3_name             | varchar(255)        | YES  | MUL | NULL    |                |
| some4_email            | varchar(255)        | YES  |     | NULL    |                |
| some4_name             | varchar(255)        | YES  | MUL | NULL    |                |
| some4_place1_gift      | varchar(255)        | YES  |     | NULL    |                |
| some4_place2_gift      | varchar(255)        | YES  |     | NULL    |                |
| some4_place3_gift      | varchar(255)        | YES  |     | NULL    |                |
+------------------------+---------------------+------+-----+---------+----------------+

table2索引

mysql> show indexes from table2;
+--------------+------------+--------------------------------------+--------------+-------------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table        | Non_unique | Key_name                             | Seq_in_index | Column_name       | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+--------------+------------+--------------------------------------+--------------+-------------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| table2       |          0 | PRIMARY                              |            1 | id                | A         |      462911 |     NULL | NULL   |      | BTREE      |         |               |
| table2       |          1 | table2_table1_table1_id_foreign     |            1 | table1_id         | A         |      462911 |     NULL | NULL   |      | BTREE      |         |               |
| table2       |          1 | some4_name_idx                       |            1 | some4_name        | A         |        5645 |     NULL | NULL   | YES  | BTREE      |         |               |
| table2       |          1 | some3_name_idx                       |            1 | some3_name        | A         |        3560 |     NULL | NULL   | YES  | BTREE      |         |               |
| table2       |          1 | some2_id_idx                         |            1 | some2_id          | A         |         116 |     NULL | NULL   |      | BTREE      |         |               |
| table2       |          1 | some1_id_idx                         |            1 | some1_id          | A         |         390 |     NULL | NULL   | YES  | BTREE      |         |               |
| table2       |          1 | some1_name_idx                       |            1 | some1_name        | A         |        1727 |     NULL | NULL   | YES  | BTREE      |         |               |
| table2       |          1 | some2_name_idx                       |            1 | some2_name        | A         |         221 |     NULL | NULL   |      | BTREE      |         |               |
+--------------+------------+--------------------------------------+--------------+-------------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
查询语句
SELECT
    table1.id AS table1_id,
    table1.field1,
    table1.date,
    table1.text,
    table2.id AS table2_id,
    table2.some1_id,
    table2.some1_name,
    table2.some2_id,
    table2.some2_name,
    table2.some3_name,
    table2.some4_email,
    table2.some4_name,
    table2.some4_place1_gift,
    table2.some4_place2_gift,
    table2.some4_place3_gift
FROM
    table2
INNER JOIN
    table1 ON table2.table1_id = table1.id
WHERE
    table2.some1_name = 'Some1_Name_Example'
    AND table2.some2_name = 'Some2_Name_Example'
    AND table2.some3_name = 'Some3_Name_Example'
    AND (
        table2.some2_id IN (1, 22, 975, 5981, 6127, 10861)
        OR table2.some1_id IN (2564, 4886, 12514, 12724, 13905, 15491, 16295, 18125, 22162, 20702, 20704, 21503)
        OR (table2.some2_id = 1277 AND table1.date < '2022-03-27 00:00:00')
        OR (table2.some2_id = 1678 AND table1.date < '2023-06-16 00:00:00')
        OR (table2.some2_id = 9519 AND table1.date < '2021-01-05 00:00:00')
        OR (table2.some1_id = 4648 AND table1.date < '2023-06-16 00:00:00')
    )
ORDER BY
    table1.date DESC,
    table2.id DESC
LIMIT 200;
执行性能与计划对比

带ORDER BY table1.date DESC的情况

  • 执行时间:1.04秒
  • EXPLAIN结果:
+----+-------------+--------------+--------+-------------------------------------------------------------------------------------------------------------------------------------------------+-----------------+---------+----------------------------+--------+---------------------------------------------------------------------+
| id | select_type | table        | type   | possible_keys                                                                                       | key             | key_len | ref                  | rows   | Extra                                                               |
+----+-------------+--------------+--------+-------------------------------------------------------------------------------------------------------------------------------------------------+-----------------+---------+----------------------------+--------+---------------------------------------------------------------------+
|  1 | SIMPLE      | table2       | ref    | table2_table1_id_foreign,some3_name_idx,some2_id_idx,some1_id_idx,some1_name_index,some2_name_index | some3_name_idx  | 768     | const                | 231455 | Using index condition; Using where; Using temporary; Using filesort |
|  1 | SIMPLE      | events       | eq_ref | PRIMARY,table1_date_idx                                                                             | PRIMARY         | 8       | db.table2.table1_id  |      1 | Using where                                                         |
+----+-------------+--------------+--------+-------------------------------------------------------------------------------------------------------------------------------------------------+-----------------+---------+----------------------------+--------+---------------------------------------------------------------------+

注:EXPLAIN中events应为table1,属于笔误

仅保留ORDER BY table2.id DESC的情况

  • 执行时间:0.12秒
  • EXPLAIN结果:
+----+-------------+--------------+--------+-------------------------------------------------------------------------------------------------------------------------------------------------+-----------------+---------+----------------------------+--------+-------------+
| id | select_type | table        | type   | possible_keys                                                                                       | key             | key_len | ref                  | rows   | Extra       |
+----+-------------+--------------+--------+-------------------------------------------------------------------------------------------------------------------------------------------------+-----------------+---------+----------------------------+--------+-------------+
|  1 | SIMPLE      | table2       | ref    | table2_table1_id_foreign,some3_name_idx,some2_id_idx,some1_id_idx,some1_name_index,some2_name_index | some3_name_idx  | 768     | const                | 231455 | Using where |
|  1 | SIMPLE      | events       | eq_ref | PRIMARY,table1_date_idx                                                                             | PRIMARY         | 8       | db.table2.table1_id  |      1 | Using where |
+----+-------------+--------------+--------+-------------------------------------------------------------------------------------------------------------------------------------------------+-----------------+---------+----------------------------+--------+-------------+

注:EXPLAIN中events应为table1,属于笔误

优化建议

1. 构建覆盖索引消除排序开销

当前查询因table1.date的索引无法和关联条件结合,导致MySQL需对23万+条结果做临时表排序。可尝试两种方案:

方案A:反向关联+复合索引

调整查询顺序从table1开始,利用table1_date_idx的有序性,同时给table2创建覆盖过滤条件与关联字段的复合索引:

-- 调整后的查询语句
SELECT
    table1.id AS table1_id,
    table1.field1,
    table1.date,
    table1.text,
    table2.id AS table2_id,
    table2.some1_id,
    table2.some1_name,
    table2.some2_id,
    table2.some2_name,
    table2.some3_name,
    table2.some4_email,
    table2.some4_name,
    table2.some4_place1_gift,
    table2.some4_place2_gift,
    table2.some4_place3_gift
FROM
    table1
INNER JOIN
    table2 ON table1.id = table2.table1_id
WHERE
    table2.some1_name = 'Some1_Name_Example'
    AND table2.some2_name = 'Some2_Name_Example'
    AND table2.some3_name = 'Some3_Name_Example'
    AND (
        table2.some2_id IN (1, 22, 975, 5981, 6127, 10861)
        OR table2.some1_id IN (2564, 4886, 12514, 12724, 13905, 15491, 16295, 18125, 22162, 20702, 20704, 21503)
        OR (table2.some2_id = 1277 AND table1.date < '2022-03-27 00:00:00')
        OR (table2.some2_id = 1678 AND table1.date < '2023-06-16 00:00:00')
        OR (table2.some2_id = 9519 AND table1.date < '2021-01-05 00:00:00')
        OR (table2.some1_id = 4648 AND table1.date < '2023-06-16 00:00:00')
    )
ORDER BY
    table1.date DESC,
    table2.id DESC
LIMIT 200;

-- 创建table2的复合索引
CREATE INDEX idx_table2_filter_join ON table2 (some3_name, some1_name, some2_name, table1_id, some2_id, some1_id);

该索引可让MySQL快速筛选符合条件的table2记录,无需回表即可获取关联table1的字段。

方案B:冗余字段+排序索引

若业务允许,将table1.date冗余到table2,并创建包含过滤、排序字段的复合索引:

-- 添加冗余字段
ALTER TABLE table2 ADD COLUMN table1_date TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP;
-- 同步历史数据
UPDATE table2 t2 JOIN table1 t1 ON t2.table1_id = t1.id SET t2.table1_date = t1.date;
-- 创建排序用复合索引
CREATE INDEX idx_table2_filter_sort ON table2 (some3_name, some1_name, some2_name, table1_date DESC, id DESC);

之后修改查询语句,直接用table2.table1_date排序,MySQL可利用索引有序性返回结果,避免临时表与文件排序。

2. 拆分OR条件为UNION ALL

原查询的OR会降低索引效率,可将每个OR分支拆分为独立查询,用UNION ALL合并后再排序:

SELECT * FROM (
    -- 分支1:some2_id IN 条件
    SELECT
        table1.id AS table1_id,
        table1.field1,
        table1.date,
        table1.text,
        table2.id AS table2_id,
        table2.some1_id,
        table2.some1_name,
        table2.some2_id,
        table2.some2_name,
        table2.some3_name,
        table2.some4_email,
        table2.some4_name,
        table2.some4_place1_gift,
        table2.some4_place2_gift,
        table2.some4_place3_gift
    FROM table2
    INNER JOIN table1 ON table2.table1_id = table1.id
    WHERE
        table2.some1_name = 'Some1_Name_Example'
        AND table2.some2_name = 'Some2_Name_Example'
        AND table2.some3_name = 'Some3_Name_Example'
        AND table2.some2_id IN (1, 22, 975, 5981, 6127, 10861)
    
    UNION ALL
    
    -- 分支2:some1_id IN 条件
    SELECT
        table1.id AS table1_id,
        table1.field1,
        table1.date,
        table1.text,
        table2.id AS table2_id,
        table2.some1_id,
        table2.some1_name,
        table2.some2_id,
        table2.some2_name,
        table2.some3_name,
        table2.some4_email,
        table2.some4_name,
        table2.some4_place1_gift,
        table2.some4_place2_gift,
        table2.some4_place3_gift
    FROM table2
    INNER JOIN table1 ON table2.table1_id = table1.id
    WHERE
        table2.some1_name = 'Some1_Name_Example'
        AND table2.some2_name = '
相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 23:22:40