我正在尝试做我认为是两个表之间的简单联接。
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_id
在 t_slv
中是唯一的,并且有一个索引开始在 nasd
上使用 symbol_id
,因此 mysql 确信它永远不必查看同一行两次。
关于mysql - 简单连接导致使用大量行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11789331/