MySQL关于select id form table where id not in (1, 2, 3)的疑问

因为业务需求, 我需要做一个向推荐用户视频的功能
要求是已经推荐过的视频, 下次不能重复推荐,
我现在有2种做法
第一种做法:
每次用户拉取推荐视频列表时把视频id都用Redis储存起来
比如拉取列表分页的第一页, 共10个视频, 我会把第一页的10个视频id存起来, 下次拉取推荐视频列表时, 我先从Redis中取出该用户的浏览过的视频id, 然后用MySQL查询出来:
select id, title form video_table where id not in (1, 2...1000) limit 10;

第二种做法:
建立一张浏览记录表user_browses, 字段是user_id, video_id
那么我每次向用户推荐视频时, 就向这张表中插入浏览记录, 下次拉取视频列表时, MySQL直接这样查询:
select id, title form video_table where id not in (select video_id from user_browses where user_id = 1) limit 10;

第一种做法是用Redis存用户的浏览记录, 可以减轻MySQL写入压力, 但是如果浏览记录特别多, 比如1000个id, 那我执行的SQL语句就特别长, 这个样子会影响MySQL的查询性能吗?

第二种做法SQL语句不会像一种做法那么长, 缺点就是MySQL会多一点写入压力, 而且查询的时候用子查询的方式,多查询一次

请问这两种做法哪种更合适?

阅读 3.1k
2 个回答

简单的做就是直接用mysql加访问记录表。可以使用memory表。

复杂的话,推荐系统一套东西就好多了。

可以使用队列异步生成用户的推荐列表数据。比如生成用户3页或4页的推荐数据。每次翻页只触发添加更新推荐数据操作,由队列去实现推荐数据更新。

mysql not in 条件太大,性能不行。

如果不用队列,也不想mysql存记录表,想用redis的话,可以存一份观看记录id,存一份全部记录id,在差值中取为观看id数据,然后再去mysql取详情。考虑数据量,视情况切分记录id。

首先 not in 的效率非常低,不会走index, 无论你这两种做法都是要修改成not exist的

我的另外一种想法:

假设A用户看过的视频数量是N个,形成一个数组。从数据库中 select id from video_table 的速度是非常快的,假设得到一个长M的数组。

你只要从 M与N的差集中随便选10个id取mysql查询就可以了。

这样mysql的压力就会变得很小,压力可以放到应用服务器上来。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏