0

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

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。

大学教师

4

1 回答 1

1

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

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

即使t_slv有很多行,该计划仍然看起来不错,因为symbol_ids 在 中是唯一的t_slv,并且有一个以symbol_idon开头的索引nasd,因此 mysql 确信它永远不必查看一行两次。

于 2012-08-03T05:01:10.617 回答