SQLServer 數(shù)據(jù)庫(kù)開(kāi)發(fā)頂級(jí)技巧
確保您的應(yīng)用程序各層數(shù)據(jù)類(lèi)型保持一致是非常重要的。例如,如果一列的數(shù)據(jù)類(lèi)型為NVARCHAR(50),那么,您應(yīng)該在代碼查詢(xún)與存儲(chǔ)過(guò)程中使用相同類(lèi)型的局部變量。
同樣,數(shù)據(jù)層中的ADO.NET代碼也應(yīng)該指定相同的數(shù)據(jù)類(lèi)型與長(zhǎng)度。為什么這很重要呢?因?yàn)槿绻麛?shù)據(jù)類(lèi)型與查詢(xún)匹配,SQL Server需要先進(jìn)行數(shù)據(jù)類(lèi)型的隱式轉(zhuǎn)換,以使它們能夠匹配。
也有一些情況,即使為參照列設(shè)置了索引,SQL Server卻不能使用此索引。因此,變量與列類(lèi)型一致的情況下,您的查詢(xún)可能會(huì)使用Index Scan而不是Index Seeking,這樣需要執(zhí)行的時(shí)間就更長(zhǎng)了。
在批處理中進(jìn)行大規(guī)模更新
開(kāi)發(fā)人員有時(shí)需要對(duì)一張表中的一列或多列中的全部或大部分列進(jìn)行數(shù)據(jù)修改。通常,對(duì)小表而言這并不是一個(gè)什么問(wèn)題。
然而,如果表很大的話(huà),您的更新語(yǔ)句將鎖定整張表,使它無(wú)法使用,甚至都不能讀取。更有甚者,對(duì)一張頻繁變化的表進(jìn)行更新可能使整個(gè)應(yīng)用程序或網(wǎng)站癱瘓。有時(shí),在極端情況下,一個(gè)大的、單個(gè)事務(wù)將導(dǎo)致事務(wù)日志急劇增長(zhǎng),并最終耗盡數(shù)據(jù)庫(kù)服務(wù)器磁盤(pán)空間。
因此,好的策略是進(jìn)行分批大規(guī)模更新,并結(jié)合頻繁的事務(wù)日志備份。以我的經(jīng)驗(yàn)看,最好一批10,000至50,000工作量。當(dāng)您開(kāi)始考慮應(yīng)用批量處理時(shí),確定閾值很困難,因?yàn)檫@取決于諸多因素比方說(shuō)如何使I/O更快,如何使表高效利用等等。
您可以考慮一個(gè)準(zhǔn)則。在ADO.NET中,典型的命令超時(shí)時(shí)間是30秒左右。當(dāng)開(kāi)始更新時(shí),其他進(jìn)程一直處于等待狀態(tài)直到更新結(jié)束。因此如果期望更新時(shí)間超過(guò)20-25秒,您最好進(jìn)行一個(gè)批處理更新。否則,將以應(yīng)用程序超時(shí)而結(jié)束。
下面這段簡(jiǎn)單的代碼展示了如何更新表中的一列,應(yīng)用的批量大小為10,000:
WHILE ( 0 = 0 )
BEGIN
UPDATE TOP ( 10000 )
Person
SET Status = 2
WHERE Status = 1
IF @@ROWCOUNT = 0
BREAK
END
應(yīng)用FOR-EACH存儲(chǔ)過(guò)程
有些時(shí)候您可能需要對(duì)某一特定類(lèi)型的所有對(duì)象執(zhí)行相同的操作。例如,您可能需要對(duì)數(shù)據(jù)庫(kù)中的所有表分配特定的權(quán)限。開(kāi)發(fā)人員經(jīng)常通過(guò)指針設(shè)置這樣的任務(wù),但是SQL Server中兩個(gè)簡(jiǎn)單的存儲(chǔ)過(guò)程可以更容易實(shí)現(xiàn):sp_msForEachTable 與 sp_msForEachDB。
每個(gè)存儲(chǔ)過(guò)程作為一個(gè)參數(shù)執(zhí)行命令。在命令中,您把表名或數(shù)據(jù)庫(kù)名作為一個(gè)問(wèn)號(hào)標(biāo)志占位符嵌入到參數(shù)中。命令運(yùn)行時(shí),SQL Server把問(wèn)號(hào)標(biāo)志替換為表名或數(shù)據(jù)庫(kù)名,并執(zhí)行。
例如,下面的代碼在Server上除TempDB外,對(duì)每個(gè)數(shù)據(jù)庫(kù)進(jìn)行全備份:
EXEC sp_msforeachdb 'IF ''?'' <> ''tempdb'' BACKUP DATABASE ?
TO DISK=''c:\backups\?.bak'' WITH INIT'
這是另外一個(gè)如何應(yīng)用這些存儲(chǔ)過(guò)程的例子。下面的代碼在禁用外鍵后,刪除數(shù)據(jù)庫(kù)所有表中的數(shù)據(jù)。當(dāng)然了,當(dāng)使用這些代碼時(shí),您需要謹(jǐn)慎的練習(xí)。
EXEC sp_MSForEachTable 'ALTER TABLE ? NOCHECK CONSTRAINT ALL'
EXEC sp_MSForEachTable '
IF OBJECTPROPERTY(object_id(''?''), ''TableHasForeignRef'') = 1
DELETE FROM ?
else
TRUNCATE TABLE ?
'
EXEC sp_MSForEachTable 'ALTER TABLE ? CHECK CONSTRAINT ALL'
建立數(shù)據(jù)庫(kù)版本
對(duì)開(kāi)發(fā)人員而言,如同對(duì)您的應(yīng)用程序版本化一樣,對(duì)數(shù)據(jù)庫(kù)執(zhí)行數(shù)字版本化是一個(gè)很好的方法。
執(zhí)行版本化并不需要很大的工作量,您只需創(chuàng)建一個(gè)包含版本號(hào)列及時(shí)間戳列的版本表即可。當(dāng)部署那些腳本時(shí),您將更好的分配每個(gè)腳本集合的版本號(hào),并對(duì)版本表進(jìn)行更新,檢查錯(cuò)誤與數(shù)據(jù)庫(kù)對(duì)比將變得更加容易。您甚至可以對(duì)腳本進(jìn)行編號(hào),這樣一來(lái)如果數(shù)據(jù)庫(kù)中建立的編號(hào)不比腳本中建立的編號(hào)高的話(huà),腳本就不執(zhí)行。樣例數(shù)據(jù)庫(kù)AdventureWorks中的AWBuildVersion就是一個(gè)很好的例子,可以看看。
盡量減少網(wǎng)絡(luò)會(huì)話(huà)
這個(gè)技巧主要針對(duì)從數(shù)據(jù)庫(kù)取數(shù)據(jù)的網(wǎng)絡(luò)應(yīng)用程序。缺乏經(jīng)驗(yàn)的開(kāi)發(fā)人員常常意識(shí)不到數(shù)據(jù)庫(kù)調(diào)用是代價(jià)很高的操作。對(duì)于小應(yīng)用程序而言,這不是什么大問(wèn)題。但是,由于很多網(wǎng)站變得非?;鸨瑢?dǎo)致數(shù)以千計(jì)的用戶(hù)同時(shí)在線(xiàn),那么您就有必要提前考慮它的可擴(kuò)展性與網(wǎng)頁(yè)加載時(shí)間的優(yōu)化問(wèn)題了。
我曾經(jīng)看到過(guò)的網(wǎng)頁(yè)有多達(dá)15個(gè)數(shù)據(jù)庫(kù)調(diào)用,而大多數(shù)正在執(zhí)行的存儲(chǔ)過(guò)程就是為了返回單獨(dú)的一行或一個(gè)值。需要牢記的是在SQL Server中一個(gè)單獨(dú)的存儲(chǔ)過(guò)程能夠返回多個(gè)結(jié)果集。在一個(gè)存儲(chǔ)過(guò)程中,您可以使用ADO.NET中的DataSet對(duì)象以及把DataTable對(duì)象組成一個(gè)集合。
相關(guān)文章
如何把sqlserver數(shù)據(jù)遷移到mysql數(shù)據(jù)庫(kù)及需要注意事項(xiàng)
由于項(xiàng)目起初用的是sqlserver數(shù)據(jù)庫(kù),后來(lái)改用了mysql數(shù)據(jù)庫(kù),那么如何把sqlserver遷移mysql呢?對(duì)sqlserver數(shù)據(jù)庫(kù)遷移感興趣的朋友可以參考下本篇文章2015-10-10SQL 統(tǒng)計(jì)一個(gè)數(shù)據(jù)庫(kù)中所有表記錄的數(shù)量
最近公司的數(shù)據(jù)庫(kù)發(fā)現(xiàn)有表的數(shù)據(jù)被弄掉了,有些數(shù)據(jù)表記錄為0,于是想找出此數(shù)據(jù)庫(kù)中到底有哪些數(shù)據(jù)表的記錄都為0以縮小分析范圍,可使用如下的SQL Statement2012-01-01sql 2000清空后讓表的id從1開(kāi)始等數(shù)據(jù)庫(kù)操作
近來(lái)發(fā)現(xiàn)數(shù)據(jù)庫(kù)過(guò)大,空間不足,因此打算將數(shù)據(jù)庫(kù)的數(shù)據(jù)進(jìn)行全面的清理,但表非常多,一張一張的清空,實(shí)在麻煩,因此就想利用SQL語(yǔ)句一次清空所有數(shù)據(jù).找到了三種方法進(jìn)行清空2012-12-12sql中循環(huán)處理當(dāng)前行數(shù)據(jù)和上一行數(shù)據(jù)相加減
曾經(jīng),sql中循環(huán)處理當(dāng)前行數(shù)據(jù)和上一行數(shù)據(jù)浪費(fèi)了我不少時(shí)間,學(xué)會(huì)后才發(fā)現(xiàn)如此容易,其實(shí)學(xué)問(wèn)就是如此,難者不會(huì),會(huì)者不難。2014-08-08解決sql server保存對(duì)象字符串轉(zhuǎn)換成uniqueidentifier失敗的問(wèn)題
這篇文章主要介紹了解決sql server保存對(duì)象字符串轉(zhuǎn)換成uniqueidentifier失敗的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-10-10SQL?Server中元數(shù)據(jù)函數(shù)的用法
這篇文章介紹了SQL?Server中元數(shù)據(jù)函數(shù)的用法,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-05-05查找sqlserver查詢(xún)死鎖源頭的方法 sqlserver死鎖監(jiān)控
如何查出SQL Server死鎖的原因,下面就教您SQL Server死鎖監(jiān)控的語(yǔ)句寫(xiě)法,下面的SQL語(yǔ)句運(yùn)行之后,便可以查找出SQLServer死鎖和阻塞的源頭2014-01-01SQL Server 數(shù)據(jù)庫(kù)分區(qū)分表(水平分表)詳細(xì)步驟
最近幾個(gè)擔(dān)心網(wǎng)站數(shù)據(jù)量大會(huì)影響sqlserver數(shù)據(jù)庫(kù)的性能,所以提前將數(shù)據(jù)庫(kù)分表處理好,下面是ExceptionalBoy同學(xué)分享的詳細(xì)方法,需要的朋友可以參考下2021-03-03SQL2005、SQL2008允許遠(yuǎn)程連接的配置說(shuō)明(附配置圖)
這篇文章主要介紹了SQL2005、SQL2008允許遠(yuǎn)程連接的配置過(guò)程,需要的朋友可以參考下2015-08-08