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

MySQL 5.1中小表LEFT JOIN大表查询速度骤降问题求助

问题

需要给一张约600万行的line表新增字段,但无法修改原表,因此创建了仅含两列的小表line_info:DI_line对应大表主键ID_line,LICLIES为需存储的属性。该小表仅约250行,但LEFT JOIN关联后查询速度慢了约1000倍,添加索引无效,使用MySQL 5.1,求优化建议。


技术信息

表结构

--
-- 表`line`的结构
--

CREATE TABLE IF NOT EXISTS `line` (
  `ID_line` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `LISOCI` char(2) DEFAULT '02',
  `LICLIE` int(11) DEFAULT '0',
  `LIADLIV` tinyint(4) NOT NULL DEFAULT '0',
  `LICMD` int(11) NOT NULL DEFAULT '0',
  `LICMDM` varchar(32) NOT NULL,
  `LILIG` int(11) NOT NULL DEFAULT '0',
  `LIARTI` varchar(8) NOT NULL,
  `LIDES1` varchar(40) NOT NULL,
  `LIDES2` varchar(40) NOT NULL,
  `LIQTE1` float DEFAULT '0',
  `LIQTE2` float DEFAULT '0',
  `LIQTE3` float DEFAULT '0',
  `LIQTE4` float DEFAULT '0',
  `LIQTE5` float DEFAULT '0',
  `LIQTE6` float DEFAULT '0',
  `LIQTE7` float DEFAULT '0',
  `LIQTE8` float DEFAULT '0',
  `LIQTE9` float DEFAULT '0',
  `LIQTE10` float DEFAULT '0',
  `LIQTE11` float DEFAULT '0',
  `LIQTE12` float DEFAULT '0',
  `LICOMMENT` varchar(80) NOT NULL,
  `LICMT1` varchar(80) NOT NULL,
  `LICMT2` varchar(80) NOT NULL,
  `LICMT3` varchar(80) NOT NULL,
  `LICMT4` varchar(80) NOT NULL,
  `LICMT5` varchar(80) NOT NULL,
  `LICMT6` varchar(80) NOT NULL,
  `LICMT7` varchar(80) NOT NULL,
  `LICMT8` varchar(80) NOT NULL,
  `LICMT9` varchar(80) NOT NULL,
  `LICMT10` varchar(80) NOT NULL,
  `LICMT11` varchar(80) NOT NULL,
  `LICMT12` varchar(80) NOT NULL,
  `LIUNIV` char(3) NOT NULL,
  `LILIBQTE` varchar(10) DEFAULT NULL,
  `LIQNIF` float NOT NULL DEFAULT '0',
  `LIDATE` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `LIPRIX` float NOT NULL DEFAULT '0',
  `LIPVCONSO` double NOT NULL DEFAULT '0',
  `LITOTAL` float NOT NULL DEFAULT '0',
  `LIPRV` double NOT NULL DEFAULT '0',
  `LILOGON` varchar(12) NOT NULL,
  `LIADRIP` varchar(16) NOT NULL,
  `LISESSION` varchar(32) NOT NULL,
  `LIGRATUIT` varchar(1) NOT NULL DEFAULT 'N',
  PRIMARY KEY (`ID_line`),
  KEY `I1` (`LISOCI`,`LICLIE`,`LICMD`,`LILIG`),
  KEY `I2` (`LISOCI`,`LICLIE`,`LICMD`,`LISESSION`,`LILIG`),
  KEY `L12` (`LICMDM`,`LILIG`),
  KEY `LICMD` (`LICMD`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=7185054 ;

--
-- 表`line_info`的结构
--

CREATE TABLE IF NOT EXISTS `line_info` (
  `DI_line` bigint(20) unsigned NOT NULL,
  `LICLIES` int(11) unsigned NOT NULL DEFAULT '0',
  PRIMARY KEY (`DI_line`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;

表状态信息

line表状态

+------+--------+---------+------------+---------+----------------+-------------+-----------------+--------------+-----------+----------------+---------------------+---------------------+---------------------+-------------------+----------+----------------+---------+
| 名称 | 引擎   | 版本    | 行格式     | 行数    | 平均行长度     | 数据长度    | 最大数据长度    | 索引长度     | 空闲数据  | 自增ID         | 创建时间            | 更新时间            | 检查时间            | 排序规则          | 校验和  | 创建选项       | 注释    |
+------+--------+---------+------------+---------+----------------+-------------+-----------------+--------------+-----------+----------------+---------------------+---------------------+---------------------+-------------------+----------+----------------+---------+
| line | MyISAM |      10 | Dynamic    | 6339101 |            179 |  1135581592 | 281474976710655 |    429571072 |      3356 |        7185054 | 2023-01-27 09:31:29 | 2023-02-06 14:49:08 | 2023-01-27 09:34:49 | latin1_swedish_ci |     NULL |                |         |
+------+--------+---------+------------+---------+----------------+-------------+-----------------+--------------+-----------+----------------+---------------------+---------------------+---------------------+-------------------+----------+----------------+---------+
1 row in set (0.00 sec)

line_info表状态

+-----------+--------+---------+------------+------+----------------+-------------+------------------+--------------+-----------+----------------+---------------------+---------------------+------------+-------------------+----------+----------------+---------+
| 名称      | 引擎   | 版本    | 行格式     | 行数 | 平均行长度     | 数据长度    | 最大数据长度     | 索引长度     | 空闲数据  | 自增ID         | 创建时间            | 更新时间            | 检查时间   | 排序规则          | 校验和  | 创建选项       | 注释    |
+-----------+--------+---------+------------+------+----------------+-------------+------------------+--------------+-----------+----------------+---------------------+---------------------+------------+-------------------+----------+----------------+---------+
| line_info | MyISAM |      10 | Fixed      |  239 |             13 |        3107 | 3659174697238527 |         6144 |         0 |           NULL | 2023-02-07 09:50:45 | 2023-02-07 09:50:45 | NULL       | latin1_swedish_ci |     NULL |                |         |
+-----------+--------+---------+------------+------+----------------+-------------+------------------+--------------+-----------+----------------+---------------------+---------------------+------------+-------------------+----------+----------------+---------+
1 row in set (0.01 sec)

查询语句及执行计划

待优化查询

EXPLAIN SELECT SQL_NO_CACHE `line`.*, `line_info`.`LICLIES` 
FROM `line` 
LEFT JOIN `line_info` ON DI_line = ID_line 
WHERE (LISOCI LIKE '02') 
AND (LICLIE IN ('44', '55') OR LICLIES IN ('44', '55')) 
AND LICMD = 0 
AND LICMDM = '' 
AND LILOGON = 'WWW' 
AND LIDATE >= '2022-12-02 16:53:56'

执行计划结果

+----+-------------+-----------+--------+-----------------+---------+---------+--------------+-------+-------------+
| id | select_type | table     | type   | possible_keys   | key     | key_len | ref          | rows  | Extra       |
+----+-------------+-----------+--------+-----------------+---------+---------+--------------+-------+-------------+
|  1 | SIMPLE      | line      | ref    | I1,I2,L12,LICMD | L12     | 34      | const        | 56594 | Using where |
|  1 | SIMPLE      | line_info | eq_ref | PRIMARY         | PRIMARY | 8       | line.ID_line |     1 | Using where |
+----+-------------+-----------+--------+-----------------+---------+---------+--------------+-------+-------------+
2 rows in set (0.00 sec)

优化建议

  • 拆分OR条件为UNION ALL查询
    原WHERE子句中的OR条件涉及两张表的字段,导致MySQL必须先关联所有行再过滤。拆分后可以分别处理两种情况,减少无效关联:

    SELECT SQL_NO_CACHE line.*, line_info.LICLIES 
    FROM line 
    LEFT JOIN line_info ON line_info.DI_line = line.ID_line 
    WHERE LISOCI = '02' 
      AND LICLIE IN ('44', '55') 
      AND LICMD = 0 
      AND LICMDM = '' 
      AND LILOGON = 'WWW' 
      AND LIDATE >= '2022-12-02 16:53:56'
    UNION ALL
    SELECT SQL_NO_CACHE line.*, line_info.LICLIES 
    FROM line 
    INNER JOIN line_info ON line_info.DI_line = line.ID_line 
    WHERE LISOCI = '02' 
      AND line_info.LICLIES IN ('44', '55') 
      AND LICMD = 0 
      AND LICMDM = '' 
      AND LILOGON = 'WWW' 
      AND LIDATE >= '2022-12-02 16:53:56'
      AND line.LICLIE NOT IN ('44', '55') -- 避免重复数据
    
  • 创建覆盖索引减少回表
    当前查询使用的L12索引只包含LICMDM和LILIG,无法覆盖其他过滤条件。创建包含所有查询条件和关联字段的覆盖索引:

    CREATE INDEX idx_line_optimize ON line (LICMDM, LICMD, LISOCI, LILOGON, LIDATE, ID_line, LICLIE);
    

    该索引可让MySQL直接从索引中获取所需数据,无需读取表数据,大幅提升查询效率。

  • *避免SELECT ,只查询必要字段
    line.*会返回40多个字段,大量数据传输会拖慢查询。明确列出需要的字段,配合覆盖索引可实现索引-only扫描,进一步提速。

  • 用子查询替代JOIN(适用于小表数据量极小的场景)
    由于line_info仅250行,可直接提取符合条件的DI_line,用IN条件替代JOIN:

    SELECT SQL_NO_CACHE line.*, 
           (SELECT LICLIES FROM line_info WHERE DI_line = line.ID_line) AS LICLIES
    FROM line 
    WHERE LISOCI = '02' 
      AND (LICLIE IN ('44', '55') OR ID_line IN (SELECT DI_line FROM line_info WHERE LICLIES IN ('44','55'))) 
      AND LICMD = 0 
      AND LICMDM = '' 
      AND LILOGON = 'WWW' 
      AND LIDATE >= '2022-12-02 16:53:56'
    
  • 强制小表使用内存临时表
    在MySQL 5.1中,可将小表查询结果放入内存临时表,减少磁盘IO:

    SELECT SQL_NO_CACHE line.*, li.LICLIES 
    FROM line 
    LEFT JOIN (SELECT * FROM line_info) li ON li.DI_line = line.ID_line 
    WHERE LISOCI = '02' 
      AND (LICLIE IN ('44', '55') OR li.LICLIES IN ('44', '55')) 
      AND LICMD = 0 
      AND LICMDM = '' 
      AND LILOGON = 'WWW' 
      AND LIDATE >= '2022-12-02 16:53:56'
    

内容的提问来源于stack exchange,提问作者user3193922

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 19:10:30