我有一个包含大量行的简单数据库。
CREATE TABLE `tbl`(
`id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
`name` NCHAR(50) NOT NULL
... other fields ...
) Engine=innodb;
我想做分页模仿。而且我知道经典的偏移是缓慢的操作。这就是为什么我尝试了这个how to automatically detect your USB drive letter
的技巧我的查询版本是
SELECT * FROM `tbl` JOIN (SELECT id FROM `tbl` ORDER BY id LIMIT 1000000, 100) as b on `b`.`id` = `tbl`.`id`;
但诀窍无效。查询工作速度非常慢,因为mysql仍然会读取所有1000000
行。
甚至分离的内部查询仅与主键有效,但不使用b树。
SELECT id FROM `tbl` ORDER BY id LIMIT 1000000, 100
那么,为什么当这个查询被它完全覆盖时,mysql引擎不使用主索引?
此外,我无法使用where id > SOME_NUMBER
条件,因为我的表格非常稀疏,并且我不知道用户请求的随机页面的边界ID。
答案 0 :(得分:2)
考虑以下内容,我强制将2.2M行放入表中
create table tbl
( id int auto_increment primary key,
thing int not null
)engine=MyISAM;
insert tbl(thing) values (7),(7),(7),(7),(7),(7),(7),(7),(7),(7),(7),(7),(7),(7),(7),(7),(7);
insert into tbl(thing) select thing from tbl;
insert into tbl(thing) select thing from tbl;
insert into tbl(thing) select thing from tbl;
insert into tbl(thing) select thing from tbl;
insert into tbl(thing) select thing from tbl;
insert into tbl(thing) select thing from tbl;
insert into tbl(thing) select thing from tbl;
insert into tbl(thing) select thing from tbl;
insert into tbl(thing) select thing from tbl;
insert into tbl(thing) select thing from tbl;
insert into tbl(thing) select thing from tbl;
insert into tbl(thing) select thing from tbl;
insert into tbl(thing) select thing from tbl;
insert into tbl(thing) select thing from tbl;
insert into tbl(thing) select thing from tbl;
insert into tbl(thing) select thing from tbl;
insert into tbl(thing) select thing from tbl;
select count(*) as theCount,max(id) as theMax,min(id) as thMin from tbl;
+----------+---------+-------+
| theCount | theMax | thMin |
+----------+---------+-------+
| 2228224 | 2228224 | 1 |
+----------+---------+-------+
explain
SELECT *
FROM `tbl`
JOIN
(SELECT id FROM `tbl` ORDER BY id LIMIT 1000000, 100) as b
on `b`.`id` = `tbl`.`id`;
+----+-------------+------------+--------+---------------+---------+---------+------+---------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+------------+--------+---------------+---------+---------+------+---------+-------------+
| 1 | PRIMARY | <derived2> | ALL | NULL | NULL | NULL | NULL | 1000100 | NULL |
| 1 | PRIMARY | tbl | eq_ref | PRIMARY | PRIMARY | 4 | b.id | 1 | NULL |
| 2 | DERIVED | tbl | index | NULL | PRIMARY | 4 | NULL | 2228224 | Using index |
+----+-------------+------------+--------+---------------+---------+---------+------+---------+-------------+
explain
SELECT t1.*
FROM tbl t1
JOIN tbl t2
on t2.id = t1.id
where t2.id>1000000
limit 100
+----+-------------+-------+--------+---------------+---------+---------+--------------------+---------+--------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+--------+---------------+---------+---------+--------------------+---------+--------------------------+
| 1 | SIMPLE | t2 | range | PRIMARY | PRIMARY | 4 | NULL | 1195836 | Using where; Using index |
| 1 | SIMPLE | t1 | eq_ref | PRIMARY | PRIMARY | 4 | so_gibberish.t2.id | 1 | NULL |
+----+-------------+-------+--------+---------------+---------+---------+--------------------+---------+--------------------------+
对于那些不熟悉使用Explain
的人,请参阅我写的here