mysql - 简单连接导致使用大量行

标签 mysql

我正在尝试做我认为是两个表之间的简单联接。

CREATE TABLE t_slv
(
    symbol_id       int                     NOT NULL,
    load_id         SMALLINT,
    val                     DECIMAL(10,4)   NOT NULL,
    -- PRIMARY KEY ( symbol_id )
    unique index ( symbol_id )
);

CREATE TABLE nasd (
    symbol_id       integer                 NOT NULL, 
    load_id         SMALLINT                NOT NULL,
    openp           DECIMAL(10,4)   NOT NULL,   -- range 0.0001 - 999,999.9999
    high            DECIMAL(10,4)   NOT NULL,
    low                     DECIMAL(10,4)   NOT NULL,
    last            DECIMAL(10,4)   NOT NULL,
    volume          integer                 NOT NULL
    -- PRIMARY KEY ( symbol_id, load_id )
    -- INDEX ( load_id )
);

CREATE UNIQUE INDEX nasd_1_ix1 on nasd( symbol_id, load_id );
CREATE UNIQUE INDEX nasd_1_ix2 on nasd( load_id, symbol_id );

所以,当我这样做时:

mysql> explain                 select  nasd.load_id
  ->                         -- nasd.low
->                 from    t_slv,
->                         nasd
->                 where   t_slv.symbol_id = nasd.symbol_id
->                         and nasd.load_id >= 4700
->                         and nasd.load_id <= 4917 ;
      +----+-------------+-------+-------+-----------------------+------------+---------+--------    --------------+---------+--------------------------+
| id | select_type | table | type  | possible_keys         | key        | key_len |   ref                  | rows    | Extra                    |
+----+-------------+-------+-------+-----------------------+------------+---------+----------------------+---------+--------------------------+
|  1 | SIMPLE      | t_slv | index | symbol_id             | symbol_id  | 4       | NULL                 |       1 | Using index              |
|  1 | SIMPLE      | nasd  | ref   | nasd_1_ix1,nasd_1_ix2 | nasd_1_ix1 | 4       | prog.t_slv.symbol_id | 2069669 | Using where; Using index |
+----+-------------+-------+-------+-----------------------+------------+---------+----------------------+---------+--------------------------+

一组 2 行(0.00 秒)

抱歉,这很难读。

如果 t_slv 中只有一行,仅将其连接到 nasd 就会导致超过 200 万行被访问。如果我取出 t_slv 并直接从表 nasd 中进行选择,则只会访问 217 行 - 这是有道理的,因为这是 4700 到 4917 之间的行数。

因此,仅连接到一个表的一行会导致访问的行数激增,即使它使用与 t_slv 不在连接中时相同的索引。

这对任何人来说都有意义吗?

现实生活中的情况实际上更糟 - 如果 t_slv 有 1000 行,则选择需要 20 分钟,这基本上使其无法运行。

即使我强制索引,我也很确定我会得到相同的结果。这意味着,即使它使用索引,它也会访问数百万行。

TIA。

最佳答案

Mysql认为t_slv中只有一行,所以它认为可以抓取这一行,从中抓取symbol_id,然后使用nasd_1_ix1 索引来查找所有匹配的行。它对 nasd 中有多少行匹配的 2M 行猜测是由于 symbol_id,load_id 索引不是唯一的这一事实而产生的,因此它无法知道您给出的范围之间有多少行。考虑到您的真实数据,它实际上不会读取那么多行。

t_slv 只有一行吗?如果没有,您可能需要重建该表,以便 mysql 对其大小有最新的了解。

即使 t_slv 有很多行,该计划看起来仍然很好,因为 symbol_idt_slv 中是唯一的,并且有一个索引开始在 nasd 上使用 symbol_id,因此 mysql 确信它永远不必查看同一行两次。

关于mysql - 简单连接导致使用大量行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11789331/

相关文章:

php - 在 MySQL PDO 查询中使用数组变量

php - 如何修复 PDO 中无效的参数号

php - 在下一个 Android Activity 中显示最近插入 MySQL 数据库的记录以进行编辑

php - Facebook用户信息存储在数据库中

mysql - 创建执行 mysql 存储过程的 windows 2000 批处理文件

php - 将循环的 MySQL 数组存储为字符串变量

php - 3 列 CSS 中的 Foreach 查询

php - 使用php在mysql中加载批量数据时出现问题

MySQL:如果存储过程中的选定字段具有 NULL 值,我想返回 N/A 作为值

mysql - LIKE 的正确语法是什么?