IT需求提示未讀信息查詢:深度技術解析與性能優化指南【類似:釘釘已讀 功能】

IT需求提示未讀信息查詢:深度技術解析與性能優化指南【類似:釘釘已讀 功能】

DROP TABLE IF EXISTS rs_kpi_it_need_tip;
CREATE TABLE IF NOT EXISTS `rs_kpi_it_need_tip`
(`id`         bigint          NOT NULL AUTO_INCREMENT COMMENT '主鍵ID,唯一標識一條提示記錄',`need_id`    bigint          NOT NULL COMMENT '關聯IT需求ID',`route_name` varchar(255)    NOT NULL COMMENT '提示位置名稱(路由名稱,如:IT需求列表)',`title`      varchar(100)    NOT NULL COMMENT '提示標題(簡潔概括提示核心內容,如:“IT需求提交前需補全附件”)',`content`    text                     DEFAULT NULL COMMENT '內容MD格式',`ct`         datetime(3)     NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '創建時間',`creator`    bigint unsigned NOT NULL COMMENT '創建人id',`ut`         datetime(3)     NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '更新時間',`updater`    bigint unsigned NOT NULL COMMENT '更新人id',`is_deleted` tinyint(1)      NOT NULL DEFAULT 0 COMMENT ' 邏輯刪除標識(0=未刪除,1=已刪除)',PRIMARY KEY (`id`),-- 索引1:按“提示位置”查詢(前端路由匹配提示時高頻使用)INDEX `idx_route_name` (`route_name`),-- 索引2:邏輯刪除+路由(避免查詢已刪除數據,提升篩選效率)INDEX `idx_is_deleted_route` (`is_deleted`, `route_name`)
) COMMENT 'IT需求提示';DROP TABLE IF EXISTS rs_kpi_it_need_tip_relation;
CREATE TABLE IF NOT EXISTS `rs_kpi_it_need_tip_relation`
(`tip_id`  bigint NOT NULL COMMENT '提示記錄ID',`user_id` bigint NOT NULL COMMENT '關聯IT需求人ID'
) COMMENT '用戶已讀-IT需求提示關系表';

一、業務模型與數據特征分析

未讀信息查詢的本質是集合差運算:需從"有效提示集合"(rs_kpi_it_need_tipis_deleted=0的記錄)中排除"用戶已讀集合"(rs_kpi_it_need_tip_relation中該用戶的tip_id)。兩張核心表的特征決定了查詢優化的方向:

表名數據增長模式核心字段基數索引現狀性能敏感點
rs_kpi_it_need_tip隨業務需求增長,總量可控(萬級至十萬級)route_name(低基數,如10-20個路由)、is_deleted(極低基數)idx_is_deleted_route聯合索引過濾未刪除+路由時需高效命中索引
rs_kpi_it_need_tip_relation隨用戶數和提示數呈線性增長(可能達百萬/千萬級)user_id(高基數)、tip_id(中高基數)無索引按用戶查詢已讀記錄時易全表掃描

關鍵結論:已讀關系表(rs_kpi_it_need_tip_relation)是性能瓶頸的核心,其索引設計直接決定查詢效率。

二、三種查詢方式的執行原理深度剖析

(一)LEFT JOIN + IS NULL:關聯過濾模式

執行鏈路
  1. 驅動表選擇:MySQL優化器通常選擇小表作為驅動表。若rs_kpi_it_need_tip過濾后數據量小(如特定路由下的提示),則作為驅動表;否則可能選擇已讀表。
  2. 關聯邏輯
    • 對驅動表每條記錄,通過ON條件(t.id = r.tip_id AND r.user_id=?)到被驅動表匹配
    • 未匹配的記錄保留,最終通過r.tip_id IS NULL過濾出未讀數據
  3. 隱式成本
    • 需生成臨時關聯結果集(內存或磁盤臨時表),大數據量時觸發Using temporary
    • 若關聯字段無索引,被驅動表需全表掃描(type: ALL),時間復雜度O(N*M)
執行計劃特征
id  select_type  table  type  key                  rows  Extra
1   SIMPLE       t      ref   idx_is_deleted_route 100   Using where; Using index
1   SIMPLE       r      ref   idx_user_tip         50    Using where; Not exists
  • 當已讀表有索引時,rtyperef,否則為ALL
  • 可能出現Using join buffer(無索引時),性能驟降

(二)NOT EXISTS:存在性判定模式

執行鏈路
  1. 主表掃描:先掃描rs_kpi_it_need_tip并過濾is_deleted=0(利用idx_is_deleted_route索引)
  2. 子查詢短路執行
    • 對主表每條記錄,執行子查詢EXISTS (SELECT 1 FROM r WHERE r.tip_id=t.id AND r.user_id=?)
    • 一旦找到匹配記錄,立即終止子查詢(短路特性),無需掃描全表
  3. 優化器優勢
    • 無需生成臨時表,直接通過布爾判斷過濾記錄
    • 子查詢可被優化為"索引查找",而非"索引掃描"
執行計劃特征
id  select_type  table  type  key                  rows  Extra
1   SIMPLE       t      ref   idx_is_deleted_route 100   Using where; Using index
1   SIMPLE       r      ref   idx_user_tip         1     Using where; Not exists
  • 子查詢typeref時,說明通過索引快速判定存在性
  • rows列接近1,表明短路執行生效

(三)NOT IN:集合排除模式

執行鏈路
  1. 子查詢執行:先執行SELECT r.tip_id FROM r WHERE user_id=?,生成已讀ID集合(臨時內存表)
  2. 主表過濾:掃描主表并判斷t.id是否不在上述集合中
  3. 風險點
    • 子查詢結果集過大時,內存占用激增(O(M)空間復雜度)
    • NULL值陷阱:若子查詢返回NULL,由于NULL <> 任何值為UNKNOWN,導致整體結果為空
    • MySQL對NOT IN優化較弱,即使有索引也可能全量掃描子查詢結果
執行計劃特征
id  select_type   table  type  key                  rows  Extra
1   PRIMARY       t      ref   idx_is_deleted_route 100   Using where; Using index
2   SUBQUERY      r      ref   idx_user_tip         50    Using index
  • 子查詢作為SUBQUERY單獨執行,結果被臨時存儲
  • 主查詢可能出現Using where; Using filesort(排序排除)

三種方式的核心差異對比

維度LEFT JOIN + IS NULLNOT EXISTSNOT IN
時間復雜度O(N log M)(有索引)O(N log M)(有索引)O(N + M)(子查詢全量)
空間復雜度O(N + M)(臨時關聯集)O(1)(無臨時集)O(M)(已讀ID集合)
索引依賴度高(需關聯字段索引)中(子查詢字段索引)高(子查詢字段索引)
大數據量適應性差(臨時集膨脹)優(短路執行)差(內存溢出風險)
NULL值兼容性兼容兼容不兼容(子查詢含NULL時)

三、索引設計的數學原理與實踐

(一)已讀關系表的最優索引:(user_id, tip_id)復合索引

設計依據
  1. 前綴匹配原則:查詢條件為user_id=? AND tip_id=?,復合索引前綴user_id可快速定位用戶
  2. 覆蓋查詢需求:索引包含tip_id,無需回表(Using index
  3. 基數權衡user_id基數高于tip_id,作為前綴可更快速過濾數據
性能提升測算
  • 無索引時:查詢某用戶已讀記錄需掃描全表(100萬行),耗時約1000ms
  • 有索引時:通過B+樹定位,僅需3-4次IO(約10ms),性能提升100倍
反例分析:(tip_id, user_id)索引為何不優?
  • 查詢條件為user_id=?,無法匹配索引前綴,導致索引失效(type: ALL

(二)主表索引的優化補充

針對路由篩選場景
  • 現有idx_is_deleted_route (is_deleted, route_name)可覆蓋WHERE is_deleted=0 AND route_name=?
  • 若需按創建時間排序(如ORDER BY ct DESC),可擴展為(is_deleted, route_name, ct)復合索引,避免Using filesort
索引選擇性驗證
-- 計算索引選擇性(越接近1越好)
SELECT COUNT(DISTINCT route_name)/COUNT(*) FROM rs_kpi_it_need_tip WHERE is_deleted=0;
  • 若選擇性低(如<0.1),索引收益有限,可能被優化器忽略

四、不同數據規模下的性能實測與調優策略

(一)中小規模數據(提示表<10萬,已讀表<100萬)

性能基準(有索引時)
查詢方式平均耗時QPS內存占用
LEFT JOIN + IS NULL80ms12500
NOT EXISTS65ms15300
NOT IN70ms14200
調優建議
  • 可根據開發習慣選擇,推薦NOT EXISTS(略優)
  • 避免SELECT *,只查詢必要字段(利用覆蓋索引)

(二)中大規模數據(提示表10萬100萬,已讀表100萬1000萬)

性能瓶頸
  • LEFT JOIN 可能觸發Using temporaryUsing filesort(臨時表排序)
  • NOT IN 子查詢結果集過大,導致內存溢出(tmp_table_size限制)
實測數據(已讀表500萬行)
查詢方式平均耗時關鍵執行計劃項
LEFT JOIN + IS NULL1200msUsing temporary
NOT EXISTS110msUsing index; Not exists
NOT IN890msUsing where; Using filesort
調優建議
  1. 強制索引:對已讀表添加FORCE INDEX (idx_user_tip)避免優化器誤判

  2. 拆分查詢:先查已讀ID到內存,再批量查詢未讀(適合應用層優化)

    List<Long> readTipIds = jdbc.query("SELECT tip_id FROM r WHERE user_id=?", ...);
    List<Tip> unreadTips = jdbc.query("SELECT * FROM t WHERE id NOT IN (?,?) AND ...", readTipIds);
    

(三)超大規模數據(提示表>100萬,已讀表>1000萬)

架構級優化
  1. 分庫分表
    • 已讀表按user_id哈希分片,避免單表過大
    • 提示表按route_name或時間范圍分區
  2. 緩存策略
    • 用Redis存儲用戶未讀計數(user:unread:count:{userId}
    • 緩存近期未讀列表(設置合理TTL,如1小時)
  3. 異步更新
    • 已讀狀態變更通過消息隊列異步寫入數據庫
    • 讀多寫少場景下,先更新緩存再異步落庫
業務妥協方案
  • 未讀數量超過閾值(如99)時顯示"99+",避免全量查詢
  • 分頁加載未讀數據,限制單頁數量(如20條)

五、數據庫引擎差異與適配

(一)MySQL vs PostgreSQL

特性MySQL 8.0PostgreSQL 14
NOT EXISTS 優化優秀(短路執行)優秀(與LEFT JOIN等效)
索引類型支持B+樹為主支持B+樹、GiST、GIN等
臨時表處理內存不足時寫入磁盤自動管理臨時表空間
執行計劃分析EXPLAIN FORMAT=JSONEXPLAIN ANALYZE(實時統計)
PostgreSQL優化建議
  • 已讀表索引:CREATE INDEX idx_user_tip ON rs_kpi_it_need_tip_relation (user_id, tip_id) INCLUDE (tip_id);(覆蓋索引)
  • 利用EXPLAIN ANALYZE獲取實際執行時間,精準調優

(二)索引維護策略

  1. 定期重建:已讀表索引碎片化嚴重時(SHOW INDEX FROM r查看Cardinality

    ALTER TABLE rs_kpi_it_need_tip_relation REBUILD INDEX idx_user_tip;
    
  2. 統計信息更新

    ANALYZE rs_kpi_it_need_tip_relation;  -- PostgreSQL
    ANALYZE TABLE rs_kpi_it_need_tip_relation;  -- MySQL
    

    確保優化器獲取準確的行數估算,避免錯誤的執行計劃

六、結論與最佳實踐

核心結論

  1. 查詢方式優先級NOT EXISTS > LEFT JOIN + IS NULL > NOT IN(全場景適用)
  2. 索引必須項rs_kpi_it_need_tip_relation添加(user_id, tip_id)復合索引,無妥協空間
  3. 性能臨界點:已讀表數據量超過100萬行時,必須通過索引+執行計劃分析進行優化

分步實施指南

  1. 緊急優化:立即為已讀表添加(user_id, tip_id)索引
  2. 中期優化:將生產環境查詢統一遷移至NOT EXISTS模式,清理SELECT *
  3. 長期規劃
    • 監控已讀表數據增長趨勢,達千萬級時啟動分庫分表
    • 引入緩存層降低數據庫壓力,尤其高頻查詢場景

通過以上深度優化,未讀信息查詢的響應時間可從秒級降至毫秒級,支撐高并發業務場景(如10萬用戶同時在線查詢)。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/96131.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/96131.shtml
英文地址,請注明出處:http://en.pswp.cn/web/96131.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Django中的軟刪除

軟刪除&#xff08;Soft Delete&#xff09;是一種數據刪除策略&#xff0c;它并不真正從數據庫中刪除記錄&#xff0c;而是通過標記&#xff08;如 is_deleted 字段&#xff09;來表示記錄已被刪除。 這樣做的好處是可以保留數據歷史&#xff0c;支持數據恢復和審計。 在 Djan…

JavaEE 進階第四期:開啟前端入門之旅(四)

專欄&#xff1a;JavaEE 進階躍遷營 個人主頁&#xff1a;手握風云 目錄 一、常用CSS 1.1. border 1.2. width/height 1.3. padding&#xff1a;內邊距 1.4. margin&#xff1a;外邊距 二、初始JavaScript 2.1. JavaScript是什么 2.2. 發展歷史 2.3. JavaScript 和 HT…

學習日記-SpringMVC-day49-9.4

知識點&#xff1a;1.RequestMapping&#xff08;3&#xff09;知識點核心內容重點RequestMapping注解的parameters屬性通過parameters指定請求參數條件&#xff08;如bookID&#xff09;&#xff0c;控制請求匹配規則&#xff08;必須包含/排除特定參數或值&#xff09;參數存…

【Day 50 】Linux-nginx反向代理與負載均衡

概述在現代 Web 架構中&#xff0c;Nginx 作為高并發、高性能的 HTTP 和反向代理服務器&#xff0c;被廣泛應用于提升服務性能、增強系統安全性和實現負載均衡。其中&#xff0c;反向代理能夠隱藏后端服務器信息并優化請求處理流程&#xff0c;負載均衡則可將請求分發到多個后端…

vue中配置 ts

在 Vue 項目中配置 TypeScript&#xff08;TS&#xff09;可以提升代碼的類型安全性和開發體驗。以下是在 Vue 項目&#xff08;基于 Vite&#xff09;中配置 TypeScript 的詳細步驟和關鍵配置&#xff1a; 一、創建支持 TypeScript 的 Vue 項目 如果是新建項目&#xff0c;推…

阿里云鏡像地址獲取,并安裝 docker的mysql和nginx等服務,java,python,ffmpeg,go等環境

阿里云那個鏡像地址獲取 阿里云鏡像加速器不是一個通用的 registry.cn-hangzhou.aliyuncs.com&#xff0c;而是你賬號專屬的&#xff0c;比如這樣&#xff1a; https://abcd1234.mirror.aliyuncs.com&#x1f449; 登錄阿里云控制臺獲取&#xff1a; 阿里云鏡像加速器 然后替…

conda環境導出

1. 激活你想要打包的環境首先&#xff0c;確保你激活了你要打包的 conda 環境&#xff1a;conda activate qwen2. 導出環境配置使用 conda 命令將當前環境的配置導出為一個 .yml 文件&#xff0c;記錄下環境中所有的依賴和版本&#xff1a;conda list --export > techgpt_en…

openEuler2403安裝部署Kafka

文章目錄 openEuler2403安裝部署Kafka with KRaft一、前言1.簡介2.架構3.環境 二、正文1.部署服務器2.基礎環境1&#xff09;JDK 安裝部署2&#xff09;關閉防火墻 3.單機部署1&#xff09;下載軟件包2&#xff09;修改配置文件3&#xff09;格式化存儲目錄4&#xff09;單機啟…

發布工業智能體,云從科技打造制造業AI“運營大腦”

近日&#xff0c;在2025世界智能產業博覽會重慶市工業智能體首發儀式現場&#xff0c;云從科技重磅發布經營決策-產線運營智能體&#xff0c;為制造業的智能化轉型提供了全新的解決方案。該智能體的亮相&#xff0c;不僅代表著人工智能技術在工業領域的深度應用&#xff0c;更標…

【Linux基礎】parted命令詳解:從入門到精通的磁盤分區管理完全指南

目錄 前言 1 parted命令概述 1.1 什么是parted 1.2 parted與fdisk的對比 1.3 parted的主要優勢 2 parted命令的安裝與基本語法 2.1 在不同Linux發行版中安裝parted 2.2 parted的基本語法 2.3 parted的工作模式 3 parted交互式命令詳解 3.1 交互式操作流程 3.2 主要…

如何在路由器上配置DHCP服務器?

在路由器上配置DHCP服務器的步驟因品牌&#xff08;如TP-Link、華為、小米、華碩等&#xff09;略有差異&#xff0c;但核心流程一致&#xff0c;主要包括登錄管理界面、開啟DHCP功能、設置IP地址池及相關參數。以下是通用操作指南&#xff1a; 一、準備工作 確保電腦/手機已連…

HTML和CSS學習

HTML學習 注釋 <!-- -->組成 告訴瀏覽器我是html文件<!DOCTYPE html> <title>瀏覽器標簽</title> <body> <!--- 其中是主要內容 ---> <p> 段落 </p> </body> </html> (結束點…

OpenTenBase vs MySQL vs Oracle,企業級應用數據庫實盤對比分析

摘要 因為工作久了的緣故&#xff0c;接觸過不少數據庫。公司的管理系統用的MySQL&#xff0c;財務系統用的Oracle。隨著時代發展&#xff0c;國產開源數據庫已經在性能上能與這些國際知名頂尖數據庫品牌相媲美&#xff0c;其中OpenTenBase以其開放環境和優越性能脫穎而出&…

Oracle 備份與恢復常見的七大問題

為了最大限度保障數據的安全性&#xff0c;同時能在不可預計災難的情況下保證數據的快速恢復&#xff0c;需要根據數據的類型和重要程度制定相應的備份和恢復方案。在這個過程中&#xff0c;DBA的職責就是要保證數據庫&#xff08;其它數據由其它崗位負責&#xff09;的高可用和…

StringBuilder類的數據結構和擴容方式解讀

目錄 StringBuilder是什么 核心特性&#xff1a; StringBuilder數據結構 1. 核心存儲結構&#xff08;基于父類 AbstractStringBuilder&#xff09; 2. 類定義與繼承關系 3. 數據結構的核心特點 StringBuilder數據結構的初始化方式 1. 無參構造&#xff1a;默認初始容量…

LangChain實戰(十七):構建與PDF/PPT文檔對話的AI助手

本文是《LangChain實戰課》系列的第十七篇,將專篇深入講解如何構建能夠與PDF和PPT文檔進行智能對話的AI助手。通過學習本文,您將掌握復雜格式文檔的解析技巧、文本與表格處理技術,以及實現精準問答的系統方法。 前言 在日常工作和學習中,PDF和PPT文檔是我們最常接觸的文檔…

魚眼相機模型

魚眼相機模型 最近涉及魚眼相機模型、標定使用等&#xff0c;作為記錄&#xff0c;更新很久不曾更新的博客。 文章目錄魚眼相機模型1 相機成像2 魚眼模型3 畸變3.1 適用針孔和MEI3.2 Kannala-Brandt魚眼模型4 代碼實現1 相機成像 針孔相機&#xff1a;所有光線從一個孔&#xf…

大語言模型提示詞工程詳盡實戰指南

引言&#xff1a;與大型語言模型&#xff08;LLM&#xff09;高效對話的藝術大型語言模型&#xff08;LLM&#xff09;——例如我們熟知的GPT系列、Claude、Llama等——在自然語言處理&#xff08;NLP&#xff09;領域展現了驚人的能力&#xff0c;能夠執行文本摘要、翻譯、代碼…

HTTP 請求體格式詳解

1. 概覽與概念 Content-Type&#xff1a;HTTP 請求/響應頭&#xff0c;表示消息體的媒體類型&#xff08;MIME type&#xff09;。服務端用它決定如何解析請求體。常見場景&#xff1a; 純結構化數據&#xff08;JSON&#xff09; → application/json表單 文件上傳 → multip…

事務設置和消息分發

事務 RabbitMQ是基于AMQP協議實現的&#xff0c;該協議實現了事務機制&#xff0c;因此RabbitMQ也支持事務機制. SpringAMQP也提供了對事務相關的操作&#xff0c;RabbitMQ事務允許開發者確保消息的發送和接收是原子性的&#xff0c;要么 全部成功&#xff0c;要么全部失敗.| 前…