0

私は、2 つのテーブル間の単純な結合だと思うことをしようとしています。

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 に 1 行しかない場合、それを nasd に結合するだけで 200 万行以上がアクセスされます。t_slv を取り出し、テーブル nasd から単純に選択すると、217 行だけがアクセスされます。これは、4700 から 4917 の間にある行数であるため、理にかなっています。

そのため、t_slv が結合に含まれていない場合と同じインデックスを使用していても、1 つの行を含む 1 つのテーブルに結合するだけで、アクセスされる行が爆発的に増加します。

これは誰にとっても意味がありますか?

実際の状況は実際にはもっと悪く、t_slv に 1000 行ある場合、select には 20 分かかり、実質的に実行できなくなります。

インデックスを強制しても、同じ結果が得られると確信しています。つまり、インデックスを使用しているにもかかわらず、何百万もの行にアクセスしています。

ティア。

ドン

4

1 に答える 1

1

Mysql は に行が 1 つしかないt_slvと考えているため、その 1 つの行を取得symbol_idして取得し、インデックスを使用しnasd_1_ix1て一致するすべての行を検索しても問題ないと判断します。一致する行数に関する2M 行の推測nasdは、インデックスが一意ではないという事実のアーティファクトであるsymbol_id,load_idため、指定した範囲の間にいくつの行があるかを知る方法がありません。実際のデータが与えられた場合、実際にはそれほど多くの行を読み取ることはありません。

t_slv1行しかありませんか?そうでない場合は、そのテーブルを再構築して、mysql がそのサイズを最新の状態に把握できるようにすることをお勧めします。

t_slv多くの行がある場合でも、 symbol_ids は で一意であり、 onでt_slv始まるインデックスがあるため、その計画は問題ないように見えます。symbol_idnasd

于 2012-08-03T05:01:10.617 に答える