1、IFNULL的使用

    1. select
    2. name
    3. from
    4. customer
    5. where
    6. referee_id != 2
    7. or
    8. referee_id is null


    /

    优化:

    1. select
    2. name
    3. from
    4. customer
    5. where
    6. ifnull(referee_id,0)!=2

    将null转换为0,然后变为不等于2

    2、 游戏玩法分析 II

    image.png
    一般常规的解法:

    1. select
    2. player_id,
    3. device_id
    4. from
    5. Activity
    6. where
    7. (player_id ,event_date )
    8. in
    9. (
    10. select
    11. player_id,
    12. min(event_date ) event_date
    13. from
    14. Activity
    15. group by
    16. player_id
    17. )

    我们想着再优化一下

    1. select player_id, device_id
    2. from Activity
    3. group by player_id
    4. having min(event_date)

    我们就有可能会写成这种格式,但是这种格式我们并非是player_id中最小的日期。
    min()、max() 和group by 一起用的时候 此时会发现获取到的数据不是最大/最小的;问题根源: group by 默认返回每一组的第一条数据(每一组的数据排序都是按默认顺序排序的)

    然后我们用窗口函数做一下

    1. select
    2. t.player_id ,
    3. t.device_id
    4. from
    5. (
    6. select
    7. *,
    8. row_number() over(partition by player_id order by event_date) as rk
    9. from Activity
    10. ) t
    11. where t.rk=1

    3、用union all 代替union
    我们都知道SQL语句使用union关键字后,可以 获取排重后的数据。而如果使用Union all关键字,可以获取所有数据,包含重复的数据。
    排重的过程需要遍历、排序和比较,它更耗时,更消耗CPU资源,所以如果能用union all的时候尽量不用Union。

    4、小表驱动大表
    小表驱动大表,也就是说小表的数据集驱动大表的数据集。
    in适用于左边大表,右边小表。
    exists适用于左边小表,右边大表。

    1. select * from order
    2. where user_id in(select id from user where status=1);
    1. select * from order
    2. where exists(select 1 from user where order.user_id = user.id and status=1);

    5、批量操作

    如果你有一批数据经过业务处理之后,需要插入数据,该怎么办?反例需要多次请求数据库,才能完成这批数据的插入,而正例只需要远程请求一次数据库,sql性能会得到提升,数据量越多,提升越大

    反例

    1. for(Order order : list){
    2. orderMapper.insert(order)
    3. }
    4. insert into order(id,code,user_id)
    5. values(123,'001',100);

    正例

    1. orderMapper.insertBatch(list);
    2. insert into order(id,code,user_id)
    3. values(123,'001',100),(124,'001',200);

    6、多用limit
    有时候,我们需要查询某些数据中的第一条,比如:查询某个用户下的第一个订单,想看看他第一次的首单时间。反例会根据用户id查询订单,返回订单数据,取第一个,而使用Limit 1,只返回该用户下单时间最小的那一条数据即可
    反例

    1. select id, create_date
    2. from
    3. order
    4. where user_id=123
    5. order by create_date asc;

    正例

    1. select id, create_date
    2. from
    3. order
    4. where user_id=123
    5. order by create_date asc limit 1;