系統數據查詢耗時優化解決方案


1.1 問題分析

大型應用系統,影響數據篩選查詢效率的關鍵因素之一,就是數據庫保存的原始數據和用戶期望的展示數據之間存在較大差異,后台需要執行復雜SQL語句,才能從原始數據中篩選出用戶期望的數據;而通常情況下,隨着SQL語句復雜度提高,其語句執行時間開銷會成幾何倍數遞增;

1.2 解決方案

為了解決上述問題,提高數據查詢時效,增強用戶體驗,可從以下幾項作為切入點按需選擇進行改進實施,研發人員可根據產品實際情況,選擇其中的一種或幾種技術來不斷提高產品響應速度,進一步提升產品用戶體驗。

1、原始數據預處理(物化視圖);

2、命令查詢職責分離(數據庫讀寫分離);

3、分布式數據庫應用(分庫/分表)等技術;

 

1.2.1 支持數據預處理

通常情況下,數據庫保存的原始數據和用戶期望的展示數據之間存在較大差異,后台需要執行復雜SQL語句,比如級聯多張數據表,才能從原始數據中篩選出用戶期望的數據。為了避免因拼寫復雜SQL語句導致數據查詢效率較低的問題,需要后台服務器提供數據二次預處理機制,即后台服務器可采用實時或定時方式,預先從原始數據中篩選出用戶期望的數據,然后將其存儲在特定數據庫表(這里統稱為報表)中。當用戶通過系統客戶端設定篩選條件查詢業務數據時,后台服務器不需要執行復雜查詢語句,而是直接從數據庫報表中,將用戶期望數據返回即可,從而有效提升數據查詢時效。

1.2.1.1 數據預處理技術實現

接下來以關系型數據庫MySQL為例,介紹下通過物化視圖技術,實現數據預處理的實現方案,供研發人員參考實施。

1.2.1.1.1 物化視圖介紹

物化視圖是一種特殊的物理表,“物化”(Materialized)視圖是相對普通視圖而言的。普通視圖是虛擬表,應用的局限性大,任何對視圖的查詢,數據庫都實際上轉換為視圖SQL語句的查詢。這樣對整體查詢性能的提高,並沒有實質上的好處,只是方便了業務處理邏輯實現。而物化視圖是查詢結果的預運算,物化視圖實際存儲着用戶數據,而這些用戶數據通常是表連接或聚集等耗時較多的操作的結果,這樣查詢數據時,就不需要多表關聯。物化視圖主要用於需要對查詢立即做出響應,而又不需要耗費長時間獲得結果。物化視圖的更新頻率決定了內容的及時性,可根據項目實際需要采取實時更新和定時更新兩種方式實現。

1.2.1.1.1.1 物化視圖設計

物化視圖表結構設計和用戶期望展示的數據密切相關。物化視圖表結構設計是否合理,直接影響到最終數據查詢時效。理論上物化視圖僅存儲用戶期望得到的數據,這樣用戶在查詢數據時,就不需要多個原始表關聯查詢,而直接從物化視圖中查詢,從而大幅提升數據查詢時效。

1.2.1.1.1.2 物化視圖更新

物化視圖的更新頻率決定了內容的及時性,可根據項目實際需要采取實時更新和定時更新兩種方式實現。

1.視圖實時更新(ON COMMIT):實時更新是指當原始數據庫表有數據修改時,需要同步更新物化視圖中的內容,確保物化視圖數據強一致性。通常可以借助數據庫觸發器來實現該功能,比如在原始表中按需創建觸發器,當原始表中有數據修改時,會自動調用觸發器來實現物化視圖更新。

2.視圖定時更新(ON DEMOND):應用程序或數據庫本身創建定時任務,來周期性定時更新物化視圖中的內容,確保物化視圖數據最終一致性。比如以1小時為粒度進行物化視圖自動更新。

1.2.1.1.2 物化視圖實現

MySQL不支持物化視圖技術,但可以通過觸發器、存儲過程或定時任務等多種技術,非常容易實現物化視圖技術。具體實現細節可參考以下網站內容,供研發人員參考實施。http://www.fromdual.com/mysql-materialized-views

1.2.2 命令查詢職責分離

在常規應用架構中,通常都是通過數據訪問層來修改或者查詢數據,一般修改和查詢使用的是相同的數據庫實體。在一些業務邏輯簡單的系統中可能沒有什么問題,但是隨着系統邏輯變得復雜,用戶、數據量增多時,這種設計就會出現數據庫讀寫性能問題;另外數據庫系統中的讀寫頻率比,是偏向讀,還是偏向寫,就如同一般的數據結構在查找和修改上時間復雜度不一樣,在設計數據庫系統結構時也需要考慮這樣的問題。解決方法就是使用命令查詢職責分離(CQRS)技術。

CQRS使用分離的接口將數據查詢操作(Queries)和數據修改操作(Commands)分離開來,這也意味着在查詢和更新過程中使用的數據模型是不一樣的。這樣讀和寫邏輯就隔離開來了。使用CQRS分離了讀寫職責之后,可以對數據進行讀寫分離操作來改進性能,同時提高可擴展性和安全。命令查詢職責分離(CQRS)大致邏輯如下圖所示:

 

主數據庫處理CUD,從庫處理R,從庫的的結構可以和主庫的結構完全一樣,也可以不一樣,從庫主要用來進行只讀的查詢操作。在數量上從庫的個數也可以根據查詢的規模進行擴展,在業務邏輯上,也可以根據專題從主庫中划分出不同的從庫。從庫也可以實現成ReportingDatabase(物化視圖專屬數據庫),根據查詢業務需求,從主庫中抽取一些必要的數據生成一系列查詢報表(物化視圖表)來存儲。

使用ReportingDatabase的一些優點通常可以使得查詢變得更加簡單高效:

1.ReportingDatabase的結構和數據表會針對常用的查詢請求進行設計;

2.ReportingDatabase數據庫通常會去正規化,存儲一些冗余而減少必要的Join等聯合查詢操作,使得查詢簡化和高效,一些在主數據庫中用不到的數據信息,在ReportingDatabase可以不用存儲;

3.可以對ReportingDatabase單獨重構優化,而不用去改變操作數據庫;

4.ReportingDatabase數據庫的查詢不會給操作數據庫帶來任何壓力;

5.可以針對不同的查詢請求建立不同的ReportingDatabase庫。

1.2.3 分布式數據庫應用

在常規應用架構中,通常都是通過數據訪問層來修改或者查詢數據,一般修改和查詢使用的是相同的數據庫實體。在一些業務邏輯簡單的系統中可能沒有什么問題,但是隨着系統邏輯變得復雜,用戶、數據量增多時,這種設計就會出現數據庫讀寫性能問題,此時除了可以借助命令查詢職責分離(CQRS)技術來解決性能問題外,還可以使用分布式數據庫技術來解決性能問題。分布式數據庫通常涉及到分庫分表等特性,通過分庫分表技術,將數據庫讀寫壓力從單節點分散到多節點,從而有效降低單節點數據庫讀寫壓力和避免長時間持鎖操作等待問題。

1.2.3.1 分庫

分庫可以有效降低單節點數據讀寫壓力,可以按照功能進行分庫設計。目前MySQL僅支持主從數據庫部署。該場景下,通常主庫用來寫操作,從庫用來讀操作。如果需要MySQL支持多節點分布式部署,則需要借助第三方組件來實現。我們可以使用CobarMyCatVitess等第三方開源組件,來實現MySQL分庫、分表等特性,同時這些組件不同程度上有效屏蔽了分庫、分表差異,從而簡化了多節點分布式數據庫場景下的應用業務邏輯實現。

1.2.3.2 分表

分表通常有兩種方式,分別為水平分表和垂直分表。

1.水平分表:將數據庫表中的數據分散到多表中存儲,主要解決表行數過大的問題。比如一個表很大,分割后可以降低在查詢時需要讀的數據和索引的頁數,同時也降低了索引的層數,提高查詢速度。其缺點是在查詢時需要多個表名,查詢所有數據需要union操作。

2.垂直分表:將一組邏輯相關的列分散到多表中存儲,主要解決列過長的問題。比如一個表中某些列常用,而另外一些列不常用,則可以采用垂直分表。垂直分表可以使得數據行變小,一個數據頁就能存放更多的數據,在查詢時就會減少I/O次數。其缺點是查詢所有數據時需要join操作。

分表會增加業務實現復雜度,但可以借助第三方組件來屏蔽分表差異,即通過第三方組件,使得底層數據庫分表對上層應用不可見,上層應用仍可以像操作單表一樣來操作多表。我們可以使用CobarMyCatVitess等第三方開源組件,來實現MySQL分庫、分表等特性,同時這些組件不同程度上有效屏蔽了分庫、分表差異,從而簡化了多節點分布式數據庫場景下的應用業務邏輯實現。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM