
select * from dbsource.dbname.dbo.table where guid in (select guid from tablechangelog where tablename = "table" and id < 110000);
這個運行居然要40秒以上,后來分析了一下:
1、table和tablechangelog是在不同的服務器上2、在tablechangelog有230萬記錄,ID是聚集索引在table上guid是主鍵,大概有30萬條記錄
解決步驟:
(相關資料圖)
首先執行select guid from tablechangelog where tablename="table" and id<110000,發現時間忽略不計,再次還原到同一臺服務器上測試運行,發現只要1秒:
select * from table where guid in (select guid from tablechangelog where tablename = "table" and id < 110000);
也就是說該SQL語句性能瓶頸在于網絡,而不是SQL本身。
既然問題在于網絡,那應該可以通過減少數據網絡傳遞來解決部分,登陸到目標服務器上執行此語句,發現只需要1~3秒即可。本來想GUID應該是造成該SQL執行的最大問題,沒想到居然是網絡問題,既然優化已到達效果,就暫且不用去管GUID了。
后話:
對于sqlserver的執行計劃以及I/O、CPU之類的指標看起來實在費勁,與其研究這些,不如靠實證來解決
出于唯一性和系統維護的要求,在各個表中都存在以下兩個字段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 ,
出于系統維護的要求,一般都會這樣查詢:
select * from tableA where guid not in (select guid) from tableB);
但是GUID是不做唯一索引的,且即使加了唯一索引,考慮到GUID是無序且過于分散的,如果有幾千上萬的guid的話,仍是不會走索引的。
關于ID,ID一般是遞增的,是不要進行維護即可從數據庫中獲得的,同時由ado直接返回給前端程序,以便定位和顯示。
INSERT INTO jobs (job_desc,min_lvl,max_lvl)VALUES ("Accountant",12,125)SELECT @@IDENTITY AS "Identity";
但是再由sqlserver2000升級到sqlserver2008后,發現返回的@@identtiy明顯是錯誤的,后來查了一下SQLServer2000聯機幫助,在一條 INSERT、SELECT INTO 或大容量復制語句完成后,@@IDENTITY 中包含此語句產生的最后的標識值。若此語句沒有影響任何有標識列的表,則 @@IDENTITY 返回 NULL。若插入了多個行,則會產生多個標識值,@@IDENTITY 返回最后產生的標識值。如果此語句激發一個或多個執行產生標識值的插入操作的觸發器,則語句執行后立即調用 @@IDENTITY 將返回由觸發器產生的最后的標識值。若 INSERT 或 SELECT INTO 語句失敗或大容量復制失敗,或事務被回滾,則 @@IDENTITY 值不會還原為以前的設置。發現通過SELECT IDENT_CURRENT("tablename")能夠返回正確的遞增值,但是否能獲取這個值,不得而知。
從sqlserver2005以后系統提供了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是由操作系統產生的,但是每個guid都會比前一個guid要大,這即解決了唯一性問題,又解決了排序問題,目前開發人員正準備按這個思路進行修改。
在指定計算機上創建大于先前通過該函數生成的任何 GUID 的 GUID。NEWSEQUENTIALID() 不能在查詢中引用。
注:即只能做為數據庫列的DEFAULT VALUE,不能執行類似SELECT NEWSEQUENTIALID()的語句只有當計算機沒有網卡時,NEWSEQUENTIALID() 生成的 GUID 才在該特定計算機中是唯一的。
注:這句話是錯誤的,應該是只有只有當計算機有網卡時,生成的GUID才是全球唯一您可以使用 NEWSEQUENTIALID() 生成 GUID 以減少葉級別索引上的頁爭用。