![](http://img.szonline.cn/2022/1118/20221118104248143.jpg)
select * from dbsource.dbname.dbo.table where guid in (select guid from tablechangelog where tablename = "table" and id < 110000);
這個運(yùn)行居然要40秒以上,后來分析了一下:
1、table和tablechangelog是在不同的服務(wù)器上2、在tablechangelog有230萬記錄,ID是聚集索引在table上guid是主鍵,大概有30萬條記錄
解決步驟:
(相關(guān)資料圖)
首先執(zhí)行select guid from tablechangelog where tablename="table" and id<110000,發(fā)現(xiàn)時間忽略不計,再次還原到同一臺服務(wù)器上測試運(yùn)行,發(fā)現(xiàn)只要1秒:
select * from table where guid in (select guid from tablechangelog where tablename = "table" and id < 110000);
也就是說該SQL語句性能瓶頸在于網(wǎng)絡(luò),而不是SQL本身。
既然問題在于網(wǎng)絡(luò),那應(yīng)該可以通過減少數(shù)據(jù)網(wǎng)絡(luò)傳遞來解決部分,登陸到目標(biāo)服務(wù)器上執(zhí)行此語句,發(fā)現(xiàn)只需要1~3秒即可。本來想GUID應(yīng)該是造成該SQL執(zhí)行的最大問題,沒想到居然是網(wǎng)絡(luò)問題,既然優(yōu)化已到達(dá)效果,就暫且不用去管GUID了。
后話:
對于sqlserver的執(zhí)行計劃以及I/O、CPU之類的指標(biāo)看起來實在費(fèi)勁,與其研究這些,不如靠實證來解決
出于唯一性和系統(tǒng)維護(hù)的要求,在各個表中都存在以下兩個字段GUID和ID,ID一般為聚集索引+主鍵。
[GUID] [varchar] (38) COLLATE Chinese_PRC_CI_AS NOT NULL CONSTRAINT [DF_GUID] DEFAULT ("{" + convert(char(36),newid()) + "}"),ID [int] IDENTITY (1, 1) NOT NULL ,
出于系統(tǒng)維護(hù)的要求,一般都會這樣查詢:
select * from tableA where guid not in (select guid) from tableB);
但是GUID是不做唯一索引的,且即使加了唯一索引,考慮到GUID是無序且過于分散的,如果有幾千上萬的guid的話,仍是不會走索引的。
關(guān)于ID,ID一般是遞增的,是不要進(jìn)行維護(hù)即可從數(shù)據(jù)庫中獲得的,同時由ado直接返回給前端程序,以便定位和顯示。
INSERT INTO jobs (job_desc,min_lvl,max_lvl)VALUES ("Accountant",12,125)SELECT @@IDENTITY AS "Identity";
但是再由sqlserver2000升級到sqlserver2008后,發(fā)現(xiàn)返回的@@identtiy明顯是錯誤的,后來查了一下SQLServer2000聯(lián)機(jī)幫助,在一條 INSERT、SELECT INTO 或大容量復(fù)制語句完成后,@@IDENTITY 中包含此語句產(chǎn)生的最后的標(biāo)識值。若此語句沒有影響任何有標(biāo)識列的表,則 @@IDENTITY 返回 NULL。若插入了多個行,則會產(chǎn)生多個標(biāo)識值,@@IDENTITY 返回最后產(chǎn)生的標(biāo)識值。如果此語句激發(fā)一個或多個執(zhí)行產(chǎn)生標(biāo)識值的插入操作的觸發(fā)器,則語句執(zhí)行后立即調(diào)用 @@IDENTITY 將返回由觸發(fā)器產(chǎn)生的最后的標(biāo)識值。若 INSERT 或 SELECT INTO 語句失敗或大容量復(fù)制失敗,或事務(wù)被回滾,則 @@IDENTITY 值不會還原為以前的設(shè)置。發(fā)現(xiàn)通過SELECT IDENT_CURRENT("tablename")能夠返回正確的遞增值,但是否能獲取這個值,不得而知。
從sqlserver2005以后系統(tǒng)提供了NEWSEQUENTIALID (),這個新的guid:
Creates a GUID that is greater than any GUID previously generated by this function on a specified computer since Windows was started. After restarting Windows, the GUID can start again from a lower range, but is still globally unique. When a GUID column is used as a row identifier, using NEWSEQUENTIALID can be faster than using the NEWID function. This is because the NEWID function causes random activity and uses fewer cached data pages. Using NEWSEQUENTIALID also helps to completely fill the data and index pages.
這個guid是由操作系統(tǒng)產(chǎn)生的,但是每個guid都會比前一個guid要大,這即解決了唯一性問題,又解決了排序問題,目前開發(fā)人員正準(zhǔn)備按這個思路進(jìn)行修改。
在指定計算機(jī)上創(chuàng)建大于先前通過該函數(shù)生成的任何 GUID 的 GUID。NEWSEQUENTIALID() 不能在查詢中引用。
注:即只能做為數(shù)據(jù)庫列的DEFAULT VALUE,不能執(zhí)行類似SELECT NEWSEQUENTIALID()的語句只有當(dāng)計算機(jī)沒有網(wǎng)卡時,NEWSEQUENTIALID() 生成的 GUID 才在該特定計算機(jī)中是唯一的。
注:這句話是錯誤的,應(yīng)該是只有只有當(dāng)計算機(jī)有網(wǎng)卡時,生成的GUID才是全球唯一您可以使用 NEWSEQUENTIALID() 生成 GUID 以減少葉級別索引上的頁爭用。
標(biāo)簽: 服務(wù)器上 是錯誤的 系統(tǒng)維護(hù)