亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

走向DBA[MSSQL篇] 針對(duì)大表 設(shè)計(jì)高效的存儲(chǔ)過程

系統(tǒng) 2152 0
原文: 走向DBA[MSSQL篇] 針對(duì)大表 設(shè)計(jì)高效的存儲(chǔ)過程【原理篇】 附最差性能sql語句進(jìn)化過程客串

測(cè)試的結(jié)果在 此處 ?本篇詳解一下原理


設(shè)計(jì)背景

由于歷史原因,線上庫(kù)環(huán)境數(shù)據(jù)量及其龐大,很多千萬級(jí)以上甚至過億的表。目標(biāo)是讓N張互相關(guān)聯(lián)的表 按照一張?jiān)幢頌榛恚瑪?shù)據(jù)搬移歸檔 這里我們舉例N為50 每張表數(shù)據(jù)5000W


最差性能sql進(jìn)化客串

2表KeyName 字段意義 名稱等相同 從bug01 表中取出前500條不在bug02 表中的數(shù)據(jù)

最差性能:

      SELECT TOP 500 a.KeyName FROM bug01 a LEFT JOIN bug02 b on a.KeyName = b.KeyName 

WHERE (a.KeyName not in (select distinct b.KeyName From bug02)) 

ORDER BY a.KeyName asc


    

?進(jìn)化體在篇尾揭曉


詳細(xì)設(shè)計(jì)

問題點(diǎn):性能 安全 容錯(cuò)

流程篇 為何如此設(shè)計(jì) 在下文中會(huì)解釋

step.1 源表數(shù)據(jù)過濾

這部分沒什么好說的 根據(jù)大家自己的業(yè)務(wù)場(chǎng)景設(shè)定不同的過濾規(guī)則

step.2 源表數(shù)據(jù)副本

程序的入口點(diǎn)肯定是源表了,擴(kuò)展表中的內(nèi)容都是以源表為Key來展開。那么這個(gè)展開的過程如何來做。

首先確定一些概念,這50表中的層級(jí)關(guān)系如何。可能直接和源表key鍵關(guān)聯(lián)的表只有10張。

例如我統(tǒng)計(jì)市內(nèi)所有圖書館詳細(xì)信息,那么我們以圖書館為源表。圖書館關(guān)聯(lián)書架、地址、會(huì)員信息。那么這3中信息我們分為一級(jí)別表。

書架關(guān)聯(lián)圖書類別,地址關(guān)聯(lián)街道信息,會(huì)員關(guān)聯(lián)用戶借閱信息,那么后面3者我們繼續(xù)分為二級(jí)表,......按照?qǐng)鼍袄^續(xù)擴(kuò)展。

方案1:使用游標(biāo) 循環(huán)源表 根據(jù)源表key值 處理和key相關(guān)的數(shù)據(jù)? 假設(shè)我們沒批次處理500跳源表數(shù)據(jù)

    也就是根據(jù)圖書館ID,遍歷所有節(jié)點(diǎn)。假設(shè)我們不分二級(jí)三級(jí)表,都是一級(jí)表 我們的insert操作次數(shù)是500*50。select操作同數(shù)據(jù)量

    這個(gè)給誰肯定都不大樂意,而且如果再遍歷2級(jí)表3級(jí)更難想象。

方案2:對(duì)源表key數(shù)據(jù)進(jìn)行集合,存進(jìn)變量,然后用in表達(dá)式。貌似可行。直接減少到1/500的操作次數(shù)。但是這里有個(gè)最恐怖的問題。

    變量都有長(zhǎng)度,例如varchar 最大長(zhǎng)度不能超過65535。

方案3:將源表Key做成一個(gè)查詢過濾池(相對(duì)于一級(jí)表 底層的sql where條件語句 下面會(huì)詳細(xì)介紹一下) 相對(duì)于第二種方案,我們這種似乎又將操作數(shù)提高了。

    不考慮層級(jí)的情況下,insert操作50。select操作50*2可以接受.

方案3擴(kuò)展: 對(duì)于一張大表來說 操作50次也不是什么可以樂觀的數(shù)字,并且這個(gè)50還有可能變成500,5000,50000。

      更有一個(gè)問題就是,當(dāng)你操作這500條的時(shí)候,可能會(huì)有數(shù)據(jù)干擾,你1秒前取得的這500條可不一定是1秒后的內(nèi)容。

      所以采取臨時(shí)表策略。

             CREATE TABLE #p

	(      

		OrderID varchar(50), 

		primary key (OrderID)      

	);

	SET @temp_text = 'INSERT INTO #p '+@KeyText

	--PRINT @temp_text

	EXEC (@temp_text)	

	

	SET @KeyText = 'SELECT OrderID FROM #p'

	--如果一級(jí)表關(guān)聯(lián)的操作次數(shù)比較多那么可以訪源表操作 以臨時(shí)表取代物理表

	SET @SubKeyText = 'select 一級(jí)表_A_被關(guān)聯(lián)鍵 From 一級(jí)表_A with(nolock) where 一級(jí)表_A_關(guān)聯(lián)源表鍵 in (' + @KeyText+')'

	

	CREATE TABLE #q

	(      

		OrderID varchar(50), 

		primary key (OrderID)      

	);

	SET @temp_text = 'INSERT INTO #q '+@SubKeyText

	EXEC (@temp_text)	

	SET @SubKeyText ='SELECT OrderID FROM #q'

	

	--如果一級(jí)表關(guān)聯(lián)的操作次數(shù)不多可以直接生成數(shù)據(jù)過濾池

	SET @SubKeyTextforA ='select 一級(jí)表_B_被二級(jí)關(guān)聯(lián)鍵 From 一級(jí)表_B with(nolock) where 一級(jí)表_B_關(guān)聯(lián)源表鍵 in (' + @KeyText+')'

	SET @SubKeyTextforB ='select 一級(jí)表_C_被二級(jí)關(guān)聯(lián)鍵 From 一級(jí)表_C with(nolock) where 一級(jí)表_C_關(guān)聯(lián)源表鍵 in (' + @KeyText+')'

	

	--如果存在更多層操作在此處可以繼續(xù)關(guān)聯(lián)資源過濾池 Demo只做到三層

SET @THKeyTextforA ='select 二級(jí)表_A_被三級(jí)關(guān)聯(lián)鍵 From 二級(jí)表_A with(nolock) where 二級(jí)表_A_關(guān)聯(lián)一級(jí)表鍵 in (' + @SubKeyTextforA+')'
    

?--step.3 分表歸檔操作

這個(gè)環(huán)節(jié)的問題是安全 事務(wù)如何控制 事務(wù)的大小如何衡量 如何容錯(cuò) 以及如何將程序做得可擴(kuò)展 可維護(hù)

大家根據(jù)業(yè)務(wù)場(chǎng)景 區(qū)分自己的批次范圍 拿蟲子這篇demo來說?50張千萬級(jí)大表?如果是批次5000條以上 事務(wù)要放在內(nèi)層處理 如果是5000條以下 可以放在最外層

事務(wù)的大小直接影響性能的波動(dòng)

容錯(cuò)的方案大家也可以自己設(shè)計(jì) 蟲子的程序員采用第三類表 異常表來重置 失敗了就插入 下一個(gè)批次直接就過濾

      --將錯(cuò)誤的批次訂單號(hào)入異常表

	Insert into 異常表(@ExTable) SELECT OrderID FROM #p

--@ExTable用來存放異常數(shù)據(jù) 如果當(dāng)期批次出錯(cuò) 則將本次批次訂單信息入庫(kù)@ExTable下一批次則過濾這些數(shù)據(jù)再執(zhí)行

	SET @KeyText = 'SELECT TOP '+CAST(@SynSize AS VARCHAR(10))+' '+@Base_Key+' FROM +
    
      '+@BaseTable+'+ WHERE '+@Base_Key+' not in (select '+@Base_Key+' From '+@ExTable+') ' 


    

?如何讓程序變的漂亮 可維護(hù)

我們?cè)诖鎯?chǔ)過程中同樣可以使用面試對(duì)象的思想 只不過存儲(chǔ)過程沒有類這樣的概念給我們 那么我們不妨自己設(shè)計(jì)

用什么 還是臨時(shí)表

      --一級(jí) 直接關(guān)聯(lián)源表主鍵 或?yàn)槎?jí)被關(guān)聯(lián)的主表

	INSERT INTO #k VALUES ('一級(jí)表_A',@Base_Key,@KeyText,'')					--一級(jí)表_A

	INSERT INTO #k VALUES ('一級(jí)表_B',@Base_Key,@KeyText,'')					--一級(jí)表_B

	INSERT INTO #k VALUES ('一級(jí)表_C',@Base_Key,@KeyText,'')					--一級(jí)表_C

--二級(jí) 規(guī)則間接關(guān)聯(lián)

	--@SubKeyText相關(guān)

	INSERT INTO #k VALUES ('二級(jí)表_A','二級(jí)表_A_關(guān)聯(lián)一級(jí)鍵',@SubKeyText,'')				--二級(jí)表_A

	INSERT INTO #k VALUES ('二級(jí)表_B','二級(jí)表_B_關(guān)聯(lián)一級(jí)鍵',@SubKeyText,'')				--二級(jí)表_B	

	INSERT INTO #k VALUES ('二級(jí)表_C','二級(jí)表_C_關(guān)聯(lián)一級(jí)鍵',@SubKeyText,'')				--二級(jí)表_C

--特殊處理 

	--自定義操作

	INSERT INTO #k VALUES ('特殊表','特殊表關(guān)聯(lián)鍵','自定義數(shù)據(jù)過濾方式','')			

	

	--其他 自增列處理

	--修改訂單,及其取消修改訂單狀態(tài)歷史表

	INSERT INTO #k VALUES ('自增表',@Base_Key,@KeyText,'自定義字段')


    

?--step.4 處理細(xì)節(jié)?

?游標(biāo)循環(huán)臨時(shí)表 針對(duì)每一張表操作一次

      DECLARE CUR_ORDERHEDER INSENSITIVE CURSOR FOR SELECT TableName,KeyName,temptext,colname FROM #k 

	OPEN CUR_ORDERHEDER

	FETCH CUR_ORDERHEDER INTO @Cur_Table,@Cur_Key,@Cur_W,@Cur_K

		WHILE @@FETCH_STATUS = 0

			BEGIN				

				 EXECUTE P_Task_Sub_Synchronization

				 @OutParam  = @OutParam OUT, @OutMessage = @OutMessage OUT,

			@KeyText =  @Cur_W,@Table= @Cur_Table,@Extension=@Extension,@IsDelSource=@IsDelSource,@KeyName=@Cur_Key,@ColName=@Cur_K

				 --SET @OutMessage = @OutMessage+@OutMessage

				 --PRINT @OutMessage

				 IF @OutParam <> 0  

					 BEGIN

						SET @OutMessage = @OutMessage + @Cur_Table +'操作失敗'						

						ROLLBACK TRAN

						--將錯(cuò)誤的批次訂單號(hào)入異常表

						Insert into 異常表(@ExTable) SELECT OrderID FROM #p

						DROP TABLE #k 

						DROP TABLE #p 

						DROP TABLE #q

						RETURN

					 END	

				 FETCH CUR_ORDERHEDER INTO @Cur_Table,@Cur_Key,@Cur_W,@Cur_K

			END

	ClOSE CUR_ORDERHEDER

	DEALLOCATE CUR_ORDERHEDER		


    

? --step.5 資源釋放

?--step.6 流程處理

?

這2個(gè)部分就不詳細(xì)說了 ?


最差性能sql進(jìn)化過程

step.1 not in了 就別再distinc了 distinc和not in都是臭名昭著的角色 not in后+dinstinc畫蛇添足而已

改后sql:

SELECT TOP 500 a.KeyName FROM bug01 a LEFT JOIN bug02 b on a.KeyName = b.KeyName
WHERE (a.KeyName not in (select? b.KeyName From bug02))
ORDER BY a.KeyName asc

step.2 別名 別小看別名 用圖來說話 原sql計(jì)劃

走向DBA[MSSQL篇] 針對(duì)大表 設(shè)計(jì)高效的存儲(chǔ)過程【原理篇】 附最差性能sql語句進(jìn)化過程客串

改后sql:

?SELECT TOP 500 a.KeyName FROM bug01 a LEFT JOIN bug02 b on a.KeyName = b.KeyName
WHERE (a.KeyName not in (select? c.KeyName From bug02 c ))
ORDER BY a.KeyName asc

走向DBA[MSSQL篇] 針對(duì)大表 設(shè)計(jì)高效的存儲(chǔ)過程【原理篇】 附最差性能sql語句進(jìn)化過程客串

step.3 何必要用外聯(lián)?直接過濾不就得了 嘿嘿

改后sql:

SELECT TOP 500 a.KeyName FROM bug01 a
WHERE (a.KeyName not in (select? c.KeyName From bug02 c))
ORDER BY a.KeyName asc

step.4 根據(jù)luofer同學(xué)的建議 再進(jìn)化一次 直接EXCEPT

SELECT TOP 500 a.KeyName FROM bug01 a except
SELECT b.KeyName from bug02 b


本篇就講到此處 歡迎大家討論

走向DBA[MSSQL篇] 針對(duì)大表 設(shè)計(jì)高效的存儲(chǔ)過程【原理篇】 附最差性能sql語句進(jìn)化過程客串


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號(hào)聯(lián)系: 360901061

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對(duì)您有幫助就好】

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對(duì)您有幫助,請(qǐng)用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長(zhǎng)會(huì)非常 感謝您的哦!!!

發(fā)表我的評(píng)論
最新評(píng)論 總共0條評(píng)論
主站蜘蛛池模板: 成人欧美视频免费看黄黄 | 国产免费播放一区二区三区 | 久久精品这里热有精品 | 综合7799亚洲伊人爱爱网 | 亚洲成人性视频 | 国产不卡在线看 | a在线视频| 热久久精品在线 | 亚洲国产精品一区二区三区 | 日本一级特大毛片 | 国内自拍 在线播放 网红 | 狠狠色伊人亚洲综合第8页 狠狠色综合久久丁香婷婷 狠狠色综合久久婷婷 | 性丰满妇女free性性性 | 一级毛片看真人在线视频 | 伊人在线| 精久久| 三级黄毛片 | 神马影院我不卡手机版 | 久久国产99 | 久草在线中文最新视频 | 久久精品免视看国产陈冠希 | 99九九99九九九视频精品 | 在线观看色 | 人人爱天天做夜夜爽毛片 | 亚洲成人免费在线视频 | 四虎影视永久免费观看网址 | 久久精品在线观看 | 久久综合精品国产一区二区三区 | 国产精品久久久久久久免费大片 | 波多野结衣中文字幕一区二区三区 | 天天舔天天射天天干 | 日日摸夜夜欧美一区二区 | 538在线视频二三区视视频 | 国产成人亚洲精品乱码在线观看 | 大学生一级毛片 | 亚洲一区二区三区不卡在线播放 | 精品亚洲大全 | 免费观看羞羞视频网站 | 爱插综合网 | 国产精品美女久久久久 | 久久亚洲国产精品五月天 |