insert into t_n values(1),(2),(3),(4),(5),(6),(7),(8),(9),(10), (11),(12),(13),(14),(15),(16),(17),(18),(19),(20);
create table t_abc( id int not null auto_increment, a int not null, b int not null, c int not null, d int not null, padding varchar(200), primary key(id), key idx_abc(a,b,c) ) engine=innodb;
insert into t_abc(a,b,c,d, padding) select t1.a, t2.a, t3.a, t3.a, rpad('', 200, 'ABC DEF G XYZ') from t_n t1, t_n t2, t_n t3;
根据测试表t_abc的结构,分析下面这几个SQL语句的执行路径,有哪些区别?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
-- SQL 1 select * from t_abc where a = 10 and b = 10; -- SQL 2 select * from t_abc where a = 10 and c = 10; -- SQL 3 select * from t_abc where a = 10 and d = 10;
-- SQL 4 select * from t_abc where a = 10 order by a,c; -- SQL 5 select * from t_abc where a = 10 order by b,c;
-- SQL 6 select id, a, b, c from t_abc where a = 10; -- SQL 7 select id, a, b, c from t_abc where b = 10; -- SQL 8 select id, a, b, c, d from t_abc where b = 10;
mysql> explain select id, a, b, c from t_abc where b = 10; +----+-------------+-------+-------+---------------+---------+---------+------+----------------------------------------+ | id | select_type | table | type | possible_keys | key | key_len | rows | Extra | +----+-------------+-------+-------+---------------+---------+---------+------+----------------------------------------+ | 1 | SIMPLE | t_abc | range | idx_abc | idx_abc | 8 | 793 | Using where; Using index for skip scan | +----+-------------+-------+-------+---------------+---------+---------+------+----------------------------------------+
select * from t_business where (id1, id2, id3) > ('id1', 'id2', 'id3') order by id1, id2, id3 limit 1000
另一种方法是使用下面这种写法。
1 2 3 4 5 6 7
select * from t_business where (id1 > 'id1') or (id1 = 'id1' and id2 > 'id2') or (id1 = 'id1' and id2 = 'id2' and id3 > 'id3') order by id1, id2, id3 limit 1000
select count(*) from t_order_detail where seller_id = ? and order_status in (?) and refund_status in(?) and is_deleted=0;
select t2.* from ( select id from t_order_detail where seller_id = ? and order_status in (?) and refund_status in(?) and is_deleted=0 order by create_time limit M, N) t1 straight_join t_order_detail t2 where t1.id = t2.id;
create table t_jointab( id int not null auto_increment, a int not null, b int not null, c varchar(4000), primary key(id), key idx_a(a) ) engine=innodb charset utf8mb4;
insert into t_jointab(a,b,c) select case when n < 9000 then n else 9000 end as a, n % 1000, rpad('x', 2000, 'ABCD') from numbers where n < 10000;
收集并查看统计信息。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
mysql> analyze table t_jointab; +---------------+---------+----------+----------+ | Table | Op | Msg_type | Msg_text | +---------------+---------+----------+----------+ | rep.t_jointab | analyze | status | OK | +---------------+---------+----------+----------+ 1 row in set (0.62 sec)
mysql> select t1.item_id, sum(t1.sold) as sold from stat_item_detail t1, ( select distinct item_id from stat_item_detail t2 where t2.gmt_create >= '2026-04-26 10:30:00') t22 where t1.item_id = t22.item_id group by t1.item_id;
思路2:
1 2 3 4 5 6
select item_id, sum(sold) from ( select distinct t1.id, t1.item_id, t1.sold as sold from stat_item_detail t1, stat_item_detail t2 where t1.item_id = t2.item_id and t2.gmt_create >= '2026-04-26 10:30:00' ) t group by item_id;