一個清理和查詢都要兼顧的簡單方案
最近和開發應用的同學在討論一個需求,目前他們碰到了一些效能問題,想讓我來看看是否能夠從資料庫的角度有一些解決方案。
假設表為消費記錄,簡稱service_details,這是一個普通表,目前這個表資料量很大,需要定期去刪除一些過期的資料,至於過期的標準先暫時按照兩個星期來算。可見這是一個需求變化極快的場景。
每天的新增資料情況為幾百萬,那麼兩個星期的資料量大概就在5千萬至一億左右。
為什麼現在考慮要改進這個表呢,有一個主要的原因是他們碰到了效能瓶頸,根據他們的業務需求,他們需要每分鐘都定時去查詢這個表,然後和其它的幾個表做一個關聯,然後把查詢的結果資料顯示在前端頁面作為一個實時的展現,是的,是每分鐘都會執行。如果資料量達到了一定的程度,查詢就會慢,舊資料也越來越多,如果去刪除這部分的資料,目前是根據時間條件去刪除,使用的是delete方式,而且目前在時間欄位上也存在索引,按照這種情況似乎索引讓問題也沒有什麼改善,前段時間他們做一個實時的查詢顯示,結果剛好有一箇舊資料刪除的任務,結果刪除的操作持續時間比較長,結果其它的查詢都會掛起,新增資料的操作也被阻塞。結果一個查詢沒做出來,第二分鐘的查詢已經照例開始執行了,然後第三分鐘,最後系統就被拖的很慢。當然最後還是找我們臨時解決,kill了那些session得以臨時釋放,而對於他們來說,這種刪除操作還是比較昂貴的,每次嘗試刪除都有些提心吊膽。
所以大體瞭解了他們的需求,其實主要在一下幾個點上,
首先這個表是一個普通表,表中的資料變化較快,需要刪除舊資料。
目前的查詢邏輯是1分鐘觸發一次,當然聽起來在邏輯上似乎還是有改進的地方,不過可以看出執行頻率還是相對比較固定而且頻繁,一旦出現了某個查詢緩慢或者阻塞,就會馬上出現系統緩慢的情況。
目前的資料清理工作比較痛苦,想刪除資料,但是感覺刪除的操作持續時間較長,不刪除舊資料較多,也影響查詢。
其實我說到這裡,大家應該也猜出來了,我最後推薦他們使用分割槽表。
推薦理由如下:
首先對於主要的痛點是刪除操作,那麼最快的刪除肯定不是delete,而是truncate,但是不能truncate全表啊,我們可以truncate分割槽
然後根據刪除的策略,是保留2個星期的資料,查詢的時候是根據時間欄位來查詢,所以完全可以考慮採用分割槽欄位作為分割槽鍵值,然後透過truncate partition的方式清理分割槽,然後查詢時直接根據時間欄位可以直接訪問指定的分割槽,而不會直接訪問全表的資料,掃描100個分割槽和掃描1個分割槽,其實基數完全不同。
當然還有一個主要的問題就是分割槽的維護,開發的同事覺得這種方式聽起來不錯,不過對於新增分割槽還是存在顧慮,比如在這個專案持續了很長時間,可能只有我們知道這個邏輯,一旦他們撤出專案了,或者沒有關注忘記了,分割槽沒有繼續增加維護到時候就比較難處理了,其實對於這點來說,DBA是需要付出一些額外的工作的。當然對於解決這個問題而言都是值得的。
假設保留了6天的資料,比如到第9天的時候,就會是右邊的藍色部分
當然也不是隻是說說,網際網路公司的實踐能力就是強,今天提完,明天就馬上付諸實踐,從現在的情況來看,查詢語句是隻會掃描某一個分割槽,不過還是遇到了一些小小的問題,那就是關於統計資訊。
這個怎麼理解呢。比如分割槽p_20160105是存放2016年1月6號的資料,但是在1月5號肯定是沒有任何資料的,直到1月6號的時候才會生成大量的資料,所以按照Oracle預設的Job去收集統計資訊,收集統計資訊之後,1月6號的分割槽統計資訊還是0,在執行sql的時候還是可能出現一些問題。這個時候有一個持續的改進方法,一個就是保證統計資訊儘可能新,準確,另一個思路就是保證執行計劃的執行路徑是最優最穩定的。這樣的話就有幾個額外的附件任務,一個就是可以考慮對於統計資訊進行分割槽級的收集,當然對於某一個特定分割槽也是幾秒鐘即可搞定,而且也不會影響線上查詢,另外一個思路就是穩定執行計劃,可以考慮使用sql profile來做。
上面的方式也都已經付諸實踐,還有一個方法,就是根據每天的資料生成量,直接設定一個固定的資料統計資訊,比如每天500萬的資料,就設定這個分割槽有500萬的資料,也讓最佳化器吃一顆定心丸。
假設表為消費記錄,簡稱service_details,這是一個普通表,目前這個表資料量很大,需要定期去刪除一些過期的資料,至於過期的標準先暫時按照兩個星期來算。可見這是一個需求變化極快的場景。
每天的新增資料情況為幾百萬,那麼兩個星期的資料量大概就在5千萬至一億左右。
為什麼現在考慮要改進這個表呢,有一個主要的原因是他們碰到了效能瓶頸,根據他們的業務需求,他們需要每分鐘都定時去查詢這個表,然後和其它的幾個表做一個關聯,然後把查詢的結果資料顯示在前端頁面作為一個實時的展現,是的,是每分鐘都會執行。如果資料量達到了一定的程度,查詢就會慢,舊資料也越來越多,如果去刪除這部分的資料,目前是根據時間條件去刪除,使用的是delete方式,而且目前在時間欄位上也存在索引,按照這種情況似乎索引讓問題也沒有什麼改善,前段時間他們做一個實時的查詢顯示,結果剛好有一箇舊資料刪除的任務,結果刪除的操作持續時間比較長,結果其它的查詢都會掛起,新增資料的操作也被阻塞。結果一個查詢沒做出來,第二分鐘的查詢已經照例開始執行了,然後第三分鐘,最後系統就被拖的很慢。當然最後還是找我們臨時解決,kill了那些session得以臨時釋放,而對於他們來說,這種刪除操作還是比較昂貴的,每次嘗試刪除都有些提心吊膽。
所以大體瞭解了他們的需求,其實主要在一下幾個點上,
首先這個表是一個普通表,表中的資料變化較快,需要刪除舊資料。
目前的查詢邏輯是1分鐘觸發一次,當然聽起來在邏輯上似乎還是有改進的地方,不過可以看出執行頻率還是相對比較固定而且頻繁,一旦出現了某個查詢緩慢或者阻塞,就會馬上出現系統緩慢的情況。
目前的資料清理工作比較痛苦,想刪除資料,但是感覺刪除的操作持續時間較長,不刪除舊資料較多,也影響查詢。
其實我說到這裡,大家應該也猜出來了,我最後推薦他們使用分割槽表。
推薦理由如下:
首先對於主要的痛點是刪除操作,那麼最快的刪除肯定不是delete,而是truncate,但是不能truncate全表啊,我們可以truncate分割槽
然後根據刪除的策略,是保留2個星期的資料,查詢的時候是根據時間欄位來查詢,所以完全可以考慮採用分割槽欄位作為分割槽鍵值,然後透過truncate partition的方式清理分割槽,然後查詢時直接根據時間欄位可以直接訪問指定的分割槽,而不會直接訪問全表的資料,掃描100個分割槽和掃描1個分割槽,其實基數完全不同。
當然還有一個主要的問題就是分割槽的維護,開發的同事覺得這種方式聽起來不錯,不過對於新增分割槽還是存在顧慮,比如在這個專案持續了很長時間,可能只有我們知道這個邏輯,一旦他們撤出專案了,或者沒有關注忘記了,分割槽沒有繼續增加維護到時候就比較難處理了,其實對於這點來說,DBA是需要付出一些額外的工作的。當然對於解決這個問題而言都是值得的。
假設保留了6天的資料,比如到第9天的時候,就會是右邊的藍色部分
當然也不是隻是說說,網際網路公司的實踐能力就是強,今天提完,明天就馬上付諸實踐,從現在的情況來看,查詢語句是隻會掃描某一個分割槽,不過還是遇到了一些小小的問題,那就是關於統計資訊。
這個怎麼理解呢。比如分割槽p_20160105是存放2016年1月6號的資料,但是在1月5號肯定是沒有任何資料的,直到1月6號的時候才會生成大量的資料,所以按照Oracle預設的Job去收集統計資訊,收集統計資訊之後,1月6號的分割槽統計資訊還是0,在執行sql的時候還是可能出現一些問題。這個時候有一個持續的改進方法,一個就是保證統計資訊儘可能新,準確,另一個思路就是保證執行計劃的執行路徑是最優最穩定的。這樣的話就有幾個額外的附件任務,一個就是可以考慮對於統計資訊進行分割槽級的收集,當然對於某一個特定分割槽也是幾秒鐘即可搞定,而且也不會影響線上查詢,另外一個思路就是穩定執行計劃,可以考慮使用sql profile來做。
上面的方式也都已經付諸實踐,還有一個方法,就是根據每天的資料生成量,直接設定一個固定的資料統計資訊,比如每天500萬的資料,就設定這個分割槽有500萬的資料,也讓最佳化器吃一顆定心丸。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/23718752/viewspace-1971212/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 簡單的查詢
- 建立一個SpringBoot專案,實現簡單的CRUD功能和分頁查詢Spring Boot
- MySQL - 資料查詢 - 簡單查詢MySql
- Mybatis簡單查詢MyBatis
- 簡單的查詢語法
- Laravel 關聯查詢 ——一對一 簡單例子Laravel單例
- 插值查詢的簡單理解
- MySQL的簡單查詢語句MySql
- SSH:hiberate實現資料的查詢(單查詢和全查詢)
- 二分查詢的簡單理解
- SSM的查詢簡單練習+JSPSSMJS
- SpringBoot 框架MongoDB 簡單的查詢方式Spring Boot框架MongoDB
- ATM-簡單SQL查詢SQL
- Spring Data Jpa 的簡單查詢多表查詢HQL,SQL ,動態查詢, QueryDsl ,自定義查詢筆記SpringSQL筆記
- 聊聊簡單又不簡單的圖上多跳過濾查詢
- Laravel 5 關聯查詢 ——一對 N 簡單例子Laravel單例
- 嘗試讓查詢更簡單
- mysql查詢快取簡單使用MySql快取
- 實現一個簡單的輪詢演算法演算法
- 全國省市區地址查詢API:簡單易用的地址查詢服務API
- Mysql-基本練習(09-刪除單表記錄、查詢指定列資料、列的別名、簡單單表條件查詢、簡單分組查詢)MySql
- 一個簡單的構建React元件動畫方案React元件動畫
- openGauss核心分析2:簡單查詢的執行
- 對 MySQL 慢查詢日誌的簡單分析MySql
- SQL Server-簡單查詢語句SQLServer
- leetCode資料查詢筆記(簡單)LeetCode筆記
- SQL查詢的:子查詢和多表查詢SQL
- java中資料庫查詢,搭配簡單的圖形介面進行查詢Java資料庫
- 二分查詢—包括查詢第一個目標元素和最後一個目標元素
- 分享一個簡單的 laravel 應用健康檢查命令Laravel
- 寫一個簡單的Linkedlist,實現增刪改查
- 一個簡單的Vue按鈕級許可權方案Vue
- VSCode一個簡單的vue移動端適配方案VSCodeVue
- dotnet 簡單控制檯使用 KernelMemory 向量化文字嵌入生成和查詢
- 讓NoSQL支援簡單條件查詢VRSQLVR
- 解決:layUI資料表格+簡單查詢UI
- vim下多行查詢替換簡單命令
- 資料庫MySQL一般查詢日誌或者慢查詢日誌歷史資料的清理資料庫MySql
- Mac上一款簡單實用的系統清理和最佳化工具Mac