V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
xx19941215
V2EX  ›  问与答

如何快速筛选出部门下某用户未读的信件数?

  •  
  •   xx19941215 · 2021-05-06 18:22:32 +08:00 · 696 次点击
    这是一个创建于 1300 天前的主题,其中的信息可能已经有所发展或是发生改变。

    有三张表 t_letter :表示信件表 ( 60 万数据)索引如下:

    如何快速筛选出部门未读的信件数?

    t_letter_dep_map:部门的信件的关联表 ( 30 万数据) 结构如下

    如何快速筛选出部门下某用户未读的信件数?

    索引如下:

    如何快速筛选出部门未读的信件数?

    t_read:已读的数据表( 150 万数据,因为我们这个信件是区分很多状态的 比如待受理 下用户是否已读 和已受理下用户是否已读是要分开对待的,所以数据会比信件表多很多)

    结构如下

    如何快速筛选出部门下某用户未读的信件数? 索引如下:

    如何快速筛选出部门未读的信件数?

    我最开始写的 SQL 如下:

    SELECT count(distinct `t_letter`.`id`)
    FROM `t_letter`
    	LEFT JOIN `t_letter_dep_map` `t_l_d_m` ON `t_l_d_m`.`depable_id` = `t_letter`.`id`
    WHERE `t_letter`.`site_id` = 145
    	AND `del_status` = 0
    	AND (`letter_dep_id` = 206
    		AND `depable_type` = 9)
    	AND (`t_letter`.`id` NOT IN (
    			SELECT `readable_id`
    			FROM `t_read`
    			WHERE `user_id` = 33203
    				AND `cat` = 'all'
    				AND `readable_type` = 9
    		)
    		AND `t_letter`.`time` > 1619402413)
    	AND `t_letter`.`deleted_at` IS NULL
    	
    

    表示筛选出分配给部门 id 为 206 的并且用户 id 为 33203 在‘all’分类下还没有读的信件总数,这条 sql 耗时大概为 10s 。 explain 信息如下:

    如何快速筛选出部门未读的信件数? 我参照网上的教程,讲 sql 改为 left join 之后情况也没有太大变化,耗时也是 10 秒左右

    SELECT count(distinct `t_letter`.`id`)
    FROM `t_letter`
    	LEFT JOIN `t_letter_dep_map` `t_l_d_m` ON `t_l_d_m`.`depable_id` = `t_letter`.`id`
    	LEFT JOIN (select * from `t_read` where `user_id` = 33203 and `cat` = 'all' and `readable_type` = 9) as `t_r` on `t_r`.`readable_id` = `t_letter`.`id`
    WHERE `t_letter`.`site_id` = 145
    	AND `del_status` = 0
    	AND (`letter_dep_id` = 206
    		AND `depable_type` = 9)
    	AND 
    		`t_r`.`readable_id` is null
    
    		AND `t_letter`.`time` > 1619402413
    	AND `t_letter`.`deleted_at` IS NULL
    

    如何快速筛选出部门未读的信件数?

    但是我在删除了部门的信件关联表之后,速度就变得很快,

    SELECT count(distinct `t_letter`.`id`)
    FROM `t_letter`
    WHERE `t_letter`.`site_id` = 145
        AND `del_status` = 0
        AND (`t_letter`.`id` NOT IN (
                SELECT `readable_id`
                FROM `t_read`
                WHERE `user_id` = 33203
                    AND `cat` = 'all'
                    AND `readable_type` = 9
            )
            AND `t_letter`.`time` > 1619402413)
        AND `t_letter`.`deleted_at` IS NULL
    

    只需要

    如何快速筛选出部门未读的信件数? 这么短,那如何快速筛选出部门下某用户未读的信件数呢?

    xx19941215
        1
    xx19941215  
    OP
       2021-05-06 18:57:43 +08:00
    我发现主要是 left join t_letter_dep_map 这个表非常慢
    xx19941215
        2
    xx19941215  
    OP
       2021-05-06 18:59:22 +08:00
    但是不这样做 又没办法满足需求 怎么弄呢
    xx19941215
        3
    xx19941215  
    OP
       2021-05-06 19:30:27 +08:00
    谢谢大家 是因为 t_letter_dep_map 有一个字段的类型设置错误了 导致无法使用索引 。。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   4932 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 29ms · UTC 09:54 · PVG 17:54 · LAX 01:54 · JFK 04:54
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.