現有2張表 商品表和 用戶購買記錄表
create table dr_purchased ( id bigint auto_increment primary key, user_id bigint not null comment '用戶ID dr_user表ID', product_type int not null comment '商品類型', product_id bigint not null comment '產品ID dr_product表ID', goods_id int not null comment '商品ID', expire_time timestamp default '2000-01-01 00:00:00' null comment '產品過期時間', platform_id int null comment '平台類型 1:ios 2:安卓' )
create table dr_product ( id bigint auto_increment comment '商品ID' primary key, code varchar(64) default '' not null comment '商品編碼-IOS應用商店需要這個碼', name varchar(200) default '' not null comment '產品名稱', type int default 0 not null comment '商品類型', goods_id int default 0 not null comment '商品ID', price int not null comment '售價', origin_price int null comment '原價', sales_volume int default 0 null comment '銷量', remarks varchar(255) default '' not null comment '備注', online int default 1 not null comment '是否在用' ) comment '商品表';
現在有一個需求是查找用戶未購買的商品, 一般我們會寫出這樣的查詢
select * from dr_product t where not exists(select product_id from dr_purchased p where p.user_id = ? and t.id = p.product_id)
現在我們看一下explain
id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
---|---|---|---|---|---|---|---|---|---|---|---|
1 | PRIMARY | t | NULL | ALL | NULL | NULL | NULL | NULL | 92 | 100 | Using where |
2 | DEPENDENT SUBQUERY | p | NULL | ref | dr_purchased_user_id_product_type_goods_id_index | dr_purchased_user_id_product_type_goods_id_index | 8 | const | 25 | 10 | Using where |
我們可以看到type為ref確實是使用了索引,但是我們用另外一種寫法來試一試。
explain select * from dr_product t left join dr_purchased p on p.user_id=? and t.id=product_id where p.id is null;
id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
---|---|---|---|---|---|---|---|---|---|---|---|
1 | SIMPLE | t | NULL | ALL | NULL | NULL | NULL | NULL | 92 | 100 | NULL |
1 | SIMPLE | p | NULL | ref | dr_purchased_user_id_product_type_goods_id_index | dr_purchased_user_id_product_type_goods_id_index | 8 | const | 25 | 10 | Using where; Not exists |
我們可以看到執行計划沒有什么本質的區別。但是經過測試 連接查詢效率更好。
最后重要的事情要再提一遍,SQL優化,一定要具體問題具體分析,沒有萬能的解決方案