我如何在SQLServer上每天處理四億三千萬記錄

2020-11-23 站長之家

文/馬非碼

首先聲明,我只是個程式設計師,不是專業的DBA,以下這篇文章是從一個問題的解決過程去寫的,而不是一開始就給大家一個正確的結果,如果文中有不對的地方,請各位資料庫大牛給予指正,以便我能夠更好的處理此次業務。

項目背景

這是給某數據中心做的一個項目,項目難度之大令人髮指,這個項目真正的讓我感覺到了,商場如戰場,而我只是其中的一個小兵,太多的戰術,太多的高層之間的較量,太多的內幕了。具體這個項目的情況,我有空再寫相關的博文出來。

這個項目是要求做環境監控,我們暫且把受監控的設備稱為採集設備,採集設備的屬性稱為監控指標。項目要求:系統支持不少於10w個監控指標,每個監控指標的數據更新不大於20秒,存儲延遲不超過120秒。那麼,我們可以通過簡單的計算得出較理想的狀態——要存儲的數據為:每分鐘30w,每個小時1800w,也就是每天4億3千兩百萬。而實際,數據量會比這個大5%左右。(實際上大部分是信息垃圾,可以通過數據壓縮進行處理的,但是別人就是要搞你,能咋辦)

上面是項目要求的指標,我想很多有不少大數據處理經驗的同學都會呲之以鼻,就這麼點?嗯,我也看了很多大數據處理的東西,但是之前沒處理過,看別人是頭頭是道,什麼分布式,什麼讀寫分離,看起來確實很容易解決。但是,問題沒這麼簡單,上面我說了,這是一個非常惡劣的項目,是一個行業惡性競爭典型的項目。

沒有更多的伺服器,而是這個伺服器除了搭配資料庫、集中採集器(就是數據解析、告警、存儲的程序),還要支持30w點的北向接口(SNMP),在程序沒有優化之前CPU常年佔用80%以上。因為項目要求要使用雙機熱備,為了省事,減少不必要的麻煩,我們把相關的服務放在一起,以便能夠充分利用HA的特性(外部購買的HA系統)

系統數據正確性要求極其變態,要求從底層採集系統到最上層的監控系統,一條數據都不能差

我們的系統架構如下,可以看到,其中資料庫壓力非常之大,尤其在LevelA節點:

硬體配置如下:

CPU:英特爾® 至強® 處理器 E5-2609 (4核, 2.40GHz, 10MB, 6.4 GT/s)

內存:4GB (2x2GB) DDR3 RDIMM Memory, 1333MHz,ECC

硬碟:500GB 7200 RPM 3.5'' SATA3 硬碟,Raid5.

資料庫版本

採用的是SQLServer2012標準版,HP提供的正版軟體,缺少很多企業版的NB功能。

寫入瓶頸

首先遇到的第一個攔路虎就是,我們發現現有的程序下,SQLServer根本處理不了這麼多的數據量,具體情況是怎樣的呢?

我們的存儲結構

一般為了存儲大量的歷史數據,我們都會進行一個物理的分表,否則每天上百萬條的記錄,一年下來就是幾億條。因此,原來我們的表結構是這樣的:

CREATE TABLE [dbo].[His20140822]( [No] [bigint] IDENTITY(1,1) NOT NULL, [Dtime] [datetime] NOT NULL, [MgrObjId] [varchar](36) NOT NULL, [Id] [varchar](50) NOT NULL, [Value] [varchar](50) NOT NULL, CONSTRAINT [PK_His20140822] PRIMARY KEY CLUSTERED ( [No] ASC)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]) ON [PRIMARY]

No作為唯一的標識、採集設備Id(Guid)、監控指標Id(varchar(50))、記錄時間、記錄值。並以採集設備Id和監控指標Id作為索引,以便快速查找。

批量寫入

寫入當時是用BulKCopy,沒錯,就是它,號稱寫入百萬條記錄都是秒級的

public static int BatchInert(string connectionString, string desTable, DataTable dt, int batchSize = 500) { using (var sbc = new SqlBulkCopy(connectionString, SqlBulkCopyOptions.UseInternalTransaction) { BulkCopyTimeout = 300, NotifyAfter = dt.Rows.Count, BatchSize = batchSize, DestinationTableName = desTable }) { foreach (DataColumn column in dt.Columns) sbc.ColumnMappings.Add(column.ColumnName, column.ColumnName); sbc.WriteToServer(dt); } return dt.Rows.Count; }

存在什麼問題?

上面的架構,在每天4千萬的數據都是OK的。但是,調整為上述背景下的配置時,集中監控程序就內存溢出了,分析得知,接收的太多數據,放在了內存中,但是沒有來得及寫入到資料庫中,最終導致了生成的數據大於消費的數據,導致內存溢出,程序無法工作。

瓶頸到底在哪裡?

是因為RAID磁碟的問題?是數據結構的問題?是硬體的問題?是SQLServer版本的問題?是沒有分區表的問題?還是程序的問題?

當時時間只有一個星期,一個星期搞不好,項目監管就要我們滾蛋了,於是,有了連續工作48小時的壯舉,有了到處打電話求人的抓雞……

但是,這個時候需要的是冷靜,再冷靜……SQLServer版本?硬體?目前都不大可能換的。RAID磁碟陣列,應該不是。那麼到底是什麼,真TM的冷靜不下來。

大家可能體會不到現場那種緊張的氣氛,其實過了這麼久,我自己也都很難再回到那種情境。但是可以這麼說,或許我們現在有了各種方法,或者處於局外人我們有更多思考,但是當一個項目壓迫你快到放棄的時候,你那時的想法、考慮在現場環境因素的制約下,都可能出現重大的偏差。有可能讓你快速的思考,也有可能思維停滯。有些同事在這種高壓的環境下,甚至出現了更多的低級錯誤,思維已經完全亂了,效率更低了……36小時沒有合眼,或者只在工地上(下雨天到處都是泥巴,幹了的話到時都是泥灰)眯兩三個小時,然後繼續幹,連續這麼一個星期!或者還要繼續!

很多人給了很多想法,但是好像有用,又好像沒用。等等,為什麼是「好像有用,又好像沒用」?我隱隱約約中,好像抓住了一絲方向,到底是什麼?對了,驗證,我們現在是跑在現場環境下,之前沒有問題,不代表現在的壓力下沒有問題,要在一個大型系統中分析這麼個小功能,影響太大了,我們應該分解它。是的,是「單元測試」,就是單個方法的測試,我們需要驗證每個函數,每個獨立的步驟到底耗時在哪裡?

逐步測試驗證系統瓶頸

修改BulkCopy的參數

首先,我想到的是,修噶BulkCopy的各項參數,BulkCopyTimeout、BatchSize,不斷的測試調整,結果總是在某個範圍波動,實際並沒有影響。或許會影響一些CPU計數,但是遠遠沒有達到我的期望,寫入的速度還是在5秒1w~2w波動,遠遠達不到要求20秒內要寫20w的記錄。

按採集設備存儲

是的,上述結構按每個指標每個值為一條記錄,是不是太多的浪費?那麼按採集設備+採集時間作為一條記錄是否可行?問題是,怎麼解決不同採集設備屬性不一樣的問題?這時,一個同事發揮才能了,監控指標+監控值可以按XML格式存儲。哇,還能這樣?查詢呢,可以用for XML這種形式。

於是有了這種結構:No、MgrObjId、Dtime、XMLData

結果驗證,比上面的稍微好點,但是不是太明顯。

數據表分區???

那個時候還沒有學會這個技能,看了下網上的文章,好像挺複雜的,時間不多了,不敢嘗試。

停止其他程序

我知道這個肯定是不行的,因為軟體、硬體的架構暫時沒法修改。但是我希望驗證是不是這些因素影響的。結果發現,提示確實明顯,但是還是沒有達到要求。

難道是SQLServer的瓶頸?

沒轍了,難道這就是SQLServer的瓶頸?上網查了下相關的資料,可能是IO的瓶頸,尼瑪,還能怎麼辦,要升級伺服器,要更換資料庫了嗎,但是,項目方給嗎?

等等,好像還有個東西,索引,對索引!索引的存在會影響插入、更新

去掉索引

是的,去掉索引之後查詢肯定慢,但是我必須先驗證去掉索引是否會加快寫入。如果果斷把MgrObjId和Id兩個欄位的索引去掉。

運行,奇蹟出現了,每次寫入10w條記錄,在7~9秒內完全可以寫入,這樣就達到了系統的要求。

查詢怎麼解決?

一個表一天要4億多的記錄,這是不可能查詢的,在沒有索引的情況下。怎麼辦!?我又想到了我們的老辦法,物理分表。是的,原來我們按天分表,那麼我們現在按小時分表。那麼24個表,每個表只需存儲1800w條記錄左右。

然後查詢,一個屬性在一個小時或者幾個小時的歷史記錄。結果是:慢!慢!!慢!!!去掉索引的情況下查詢1000多萬的記錄根本是不可想像的。還能怎麼辦?

繼續分表,我想到了,我們還可以按底層的採集器繼續分表,因為採集設備在不同的採集器中是不同的,那麼我們查詢歷史曲線時,只有查單個指標的歷史曲線,那麼這樣就可以分散在不同的表中了。

說幹就幹,結果,通過按10個採集嵌入式並按24小時分表,每天生成240張表(歷史表名類似這樣:His_001_2014112615),終於把一天寫入4億多條記錄並支持簡單的查詢這個問題給解決掉了!!!

查詢優化

在上述問題解決之後,這個項目的難點已經解決了一半,項目監管也不好意思過來找茬,不知道是出於什麼樣的戰術安排吧。

過了很長一段時間,到現在快年底了,問題又來了,就是要拖死你讓你在年底不能驗收其他項目。

這次要求是這樣的:因為上述是模擬10w個監控指標,而現在實際上線了,卻只有5w個左右的設備。那麼這個明顯是不能達到標書要求的,不能驗收。那麼怎麼辦呢?這些聰明的人就想,既然監控指標減半,那麼我們把時間也減半,不就達到了嗎:就是說按現在5w的設備,那你要10s之內入庫存儲。我勒個去啊,按你這個邏輯,我們如果只有500個監控指標,豈不是要在0.1秒內入庫?你不考慮下那些受監控設備的感想嗎?

但是別人要玩你,你能怎麼辦?接招唄。結果把時間降到10秒之後,問題來了,大家仔細分析上面邏輯可以知道,分表是按採集器分的,現在採集器減少,但是數量增加了,發生什麼事情呢,寫入可以支持,但是,每張表的記錄接近了400w,有些採集設備監控指標多的,要接近600w,怎麼破?

於是技術相關人員開會討論相關的舉措。

在不加索引的情況下怎麼優化查詢?

有同事提出了,where子句的順序,會影響查詢的結果,因為按你刷選之後的結果再處理,可以先刷選出一部分數據,然後繼續進行下一個條件的過濾。聽起來好像很有道理,但是SQLServer查詢分析器不會自動優化嗎?原諒我是個小白,我也是感覺而已,感覺應該跟VS的編譯器一樣,應該會自動優化吧。

具體怎樣,還是要用事實來說話:

結果同事修改了客戶端之後,測試反饋,有較大的改善。我查看了代碼:

難道真的有這麼大的影響?等等,是不是忘記清空緩存,造成了假象?

於是讓同事執行下述語句以便得出更多的信息:

--優化之前DBCC FREEPROCCACHEDBCC DROPCLEANBUFFERSSET STATISTICS IO ONselect Dtime,Value from dbo.his20140825 WHERE Dtime>='' AND Dtime<='' AND MgrObjId='' AND Id=''SET STATISTICS IO OFF--優化之後DBCC FREEPROCCACHEDBCC DROPCLEANBUFFERSSET STATISTICS IO ONselect Dtime,Value from dbo.his20140825 WHERE MgrObjId='' AND Id='' AND Dtime>='' AND Dtime<=''SET STATISTICS IO OFF

結果如下:

相關焦點

  • SQLServer DAB:十個經典實例全面解析
    【IT168技術】死鎖如何跟蹤;阻塞如何跟蹤和查找;發現有問題的語句後,如何進行處理;用Profile做跟蹤時,一般我們需要跟蹤哪些事件;  dbcc traceon(1204) 可以開打跟蹤死鎖的標記,sqlserver2005新增了1222跟蹤標誌,就是格式更詳細,死鎖的信息會記錄在errlog文件裡,順便說下errlog
  • MySQL、SqlServer、Oracle三種資料庫區別在哪裡?
    原文:http://blog.csdn.net/ttttttris/article/details/73823522作者:TanXY_915一、sqlserver作為重要的基準測試可伸縮性和速度獎的記錄保持者,SQLServer是一個具備完全Web支持的資料庫產品,提供了對可擴展標記語言 (XML)的核心支持以及在Internet上和防火牆外進行查詢的能力;缺點:開放性 :SQL Server 只能windows上運行沒有絲毫開放性作業系統系統穩定對資料庫十分重要
  • 微信運動能看訪客記錄嗎 可以幫助大家記錄每天的步數
    微信運動能看訪客記錄嗎 可以幫助大家記錄每天的步數時間:2019-07-16 15:50   來源:騰牛網   責任編輯:凌君 川北在線核心提示:原標題:微信運動能看訪客記錄嗎可以幫助大家記錄每天的步數 微信運動可以幫助大家記錄每天的步數,可以看到排行榜,朋友圈好友之間還可以相互點讚。
  • 我感恩,我的阿卡西記錄的指引
    我剛剛開始的時候,只有一點點的感覺,我知道,每天這樣重複,就可以創造奇蹟,我只是按照我的目標去做我每天應該做的事情!我一點都不問結果,我知道只有量變才有質變,我每天都在規定的時間內,做完我的阿卡西記錄的閱讀,只有做完了我的阿卡西記錄的閱讀,我才能睡覺,我非常嚴格的要求了我自己。我就這樣一直堅持到現在。
  • 微信運動到底是如何記錄步數的?步數背後的秘密是加速度
    微信運動每天的步數排名愈發受人關注,人們總會在意今天走了多少步,在好友中排名多少,獲得了幾個贊,又是誰佔領了自己的封面。為了獲得最高排名,有人也是用盡了各種辦法。那麼微信運動是如何記錄我們每天的步數的呢?   那麼,手機是如何計步的呢?步數存在的依據究竟是什麼?
  • 魚缸換了新水如何處理?我這有些建議
    魚也一樣,它的吃喝拉撒,全在這一缸水裡,你不經常給它換點新水,改善一下水環境質量,任由水質老化,惡化下去,它是一定會死給你看的那問題就來了,新換的水,我們該如何處理呢?A、較簡單的困水方法如果魚缸小,換的水量不是很多,家裡備個大口的桶,盆,等容器,讓自來水放置24小時,就可以使用,目的是拿水裡的殘氯,揮發掉。
  • 會議記錄都不會如何晉升?3招,學會記錄和升華,提升職場競爭力
    通過調查數據,我們發現往往不做會議記錄的員工,工作狀態和效率也同樣低下。具體到工作中,它主要表現在以下幾方面。那麼我就總結下「不做會議記錄,工作狀態和效率低下」的幾表現吧。大家都習慣了小趙做會議記錄,那天小趙正好出差不在公司,沒有人主動做會議記錄,導致大家一忙就把有些會議中講過的事情都忘了。周五,客戶來監察採購部門拿不出材料的環保數據,導致量產時間延後,生產受到了嚴重的影響。人的記憶力再強,每天忙碌各種複雜事情時,容易出現記憶模糊不清的現象。
  • 每天堅持自己做早餐,記錄下來,我要做最有正能量的媽媽!
    喜歡我的家常美食分享就請點讚、收藏、評論、再順手轉發一下吧!當然如果您有更好的做法,歡迎留言跟大家一起分享。雖然我不怎麼在外面吃飯,但是如果外出吃東西的話,我這個中國胃還是挺喜歡吃這種菜泡飯的,不過,我還是覺得小時候在老家那種大鍋燒的鍋巴湯再做這種湯飯更香更好吃。只是現在在城裡沒有那種大鍋燒飯,甚至連想吃鍋巴都難了呢?
  • 如何在太空中記錄時間?看似簡單實際很複雜
    建立太空殖民基地和長期飛行存在著諸多技術障礙,例如:人類如何在太空中獲取食物?我們如何處理太空垃圾?在地球上,這些問題被認為是理所當然、不足為奇。未來人類實現太空生活首先需要解決一個問題——我們如何記錄時間。記錄時間的解決方法可能很簡單,帶上手錶或者查看日曆,或者刻畫記錄每一天!
  • 看「秋日觀察員」如何記錄秋天
    看「秋日觀察員」如何記錄秋天 2020-10-27 22:05 來源:澎湃新聞·澎湃號·政務
  • 顏寧:講講如何做實驗記錄
    實驗記錄是給【未來的自己和其他成員】看的,每一天都要好好整理;也許很多內容,比如PCR、protein purification,每天同樣的內容你都煩了,但是依舊要如實記錄。別忘了,lab notes是可以用來作為呈堂證供的。我經常對學生說:你的工作體現在實驗記錄裡。我們談課題,你帶著實驗記錄本給我看,如果沒有當天的記錄,等同於沒做實驗。2.
  • 她每天記錄用藥和身體變化,只是為了……遺體捐獻;看哭了
    「我馬上就用手機查,感覺到出大問題了。」雖然身邊的醫生朋友都安慰她,炎症也可能導致這個指標偏高,不能急著下定論,還要複查才能作出準確的判斷。2018年1月19日,馬阿姨到湖州第一人民醫院做了派特CT。CT報告,是老伴一個人拿去給醫生看的。確診胰腺癌晚期,而且已經轉移到了肝上。醫生按常規推斷,馬阿姨只剩下3到6個月的生命。
  • 施工現場:你的實況記錄做好了嗎?
    在建築施工過程中的管理主要就是開會,由各工地的班組長來帶領,項目經理則在四個工地間不停地往返管理,每天早上各工地都會舉行碰頭例會,說明當日的作業要求、安全宣講等,每天結束工作後還是通過開會的方式來總結一天的施工情況,進度,材料狀況,資源調配,突發事情,是否有甲方變更需求等。
  • 怎麼在電腦上刪除QQ聊天記錄?
    有時候我們會在與好友聊天過程中談及一些敏感隱私的東西需要及時的處理,或是聊天記錄太多需要清理一下,這裡筆者就與大家分享一下怎麼去刪除QQ中的聊天記錄。打開並登陸需要處理聊天信息的QQ,點擊如圖所示位置的「打開消息管理器」圖標進行消息管理頁面。
  • 農村小豬場豬糞便如何處理更好?
    問題:豬場豬糞便如何處理更划算?答案:在農村搞養豬,糞便處理是一件大事,沒有處理好,就會汙染水源,汙染農田,影響周邊環境,影響村容村貌,造成難於彌補的損失。所以,豬糞便是農村治汙首要大問題,關係到整個農村環境整治的中心大事,是農村生態文明建設的中心大事。
  • 喬伊金是如何處理她在新劇中的角色,使她臉書上的粉絲增加了十倍
    導讀:喬伊金是如何處理她在新劇中的角色,使她臉書上的粉絲增加了十倍。今年最大的青少年電影甚至沒有在影院上映,而是在五月份上傳到Netflix。對我來說,在Instagram上保持對自己的忠誠是很重要的,對我來說,擁有某些事情也是很重要的。我在Instagram上的最後一篇帖子是我洗澡時戴著面罩,我不知道自己在做什麼哈哈大笑]這感覺像是奇怪的,私人的,但我的一部分人認為這是非常有趣的,這將是值得分享的。我儘量不想太多,因為我只會讓自己發瘋。看看我的Instagram,我很高興我如何平衡我的社會生活和工作。
  • 我非常幸運……靈魂覺醒阿卡西記錄景姐姐
    我在給人們解讀阿卡西記錄的時候,看到最多的就是人們不清楚自己要什麼?也不清晰怎麼做能夠得到自己想要的結果。過去,在我沒有做阿卡西記錄閱讀之前,我沒有意識到,人們出現的這些基本狀況。我只知道人與人之間的區別,就是想法不同造成了人與人之間的差別,也造成了人與人之間的根本差別。但是,現在我明白了在人們想法不同的前面,還有一個屏障,就是到底想要什麼?
  • 如何處理悲傷的情緒:12種方法讓你的生活恢復平靜、減少悲傷
    今天我們來分享一些有關悲傷情緒的知識,以及如何處理這種情緒的方法。什麼是悲傷?悲傷被定義為有傷心、難過或不快樂的感受。悲傷情緒也是抑鬱症的一部分,它與抑鬱症的其他症狀有關,包括自我價值感低、睡眠不佳和缺乏動力。雖然我們有時會陷入悲傷的情緒中,但我們不必一直保持這種狀態。
  • 說說我每天給我上一年級的兒子的安排大家都是怎麼做的
    我不是炫耀也不是覺得自己的方法有多好,只是把我認為的用在孩子身上,而且自己也看到了成效,分享一下。歡迎有好的建議和想法的家長可以和我一起探討!今年我兒子一年級,他從幼兒園到小學我中間焦慮過,現在孩子的表現還不錯,算是心裡安慰。
  • 數控工具機X、Y、Z軸失控了,我該如何處理?
    同時數控銑床、數控車床被大規模的配置到各產品自動化生產線上,實現了自動化無入管理。但在生產中由於數控工具機的伺服系統出現故障,會引起數控銑床在加工過程中,X軸、Y軸、Z軸同時快速移動;數控車床Y軸突然進給失控等原因。下面我們對故障現象,給予分析、檢查,並給予排除故障。