Sql-Server
由於不同的排序規則而沒有使用索引 - 有什麼解決方法嗎?
我正在執行以下查詢:
SET ROWCOUNT 50 SELECT UL.* FROM COLA.dbo.tbl_UserLogin ul INNER JOIN CABrochure.dbo.tbl_country co ON ul.CountryCode COLLATE DATABASE_DEFAULT = co.cola_countrycode COLLATE DATABASE_DEFAULT SELECT UL.* FROM COLA.dbo.tbl_UserLogin ul INNER JOIN CRMReferences.dbo.tbl_country2 co ON ul.CountryCode = co.cola_countrycode SET ROWCOUNT 0
當我查看查詢執行計劃時,我看到了:
OBS。使用的索引(表 tbl_country 和 tbl_country2)是相同的,只是我錯誤地輸入了錯誤的名稱。
CABrochure.dbo.tbl_country
表和第二個表之間的唯一區別CRMReferences.dbo.tbl_country2
是collation
.我已經創建(並填充了所有數據)與表
CRMReferences.dbo.tbl_country2
相同,但我已經為列中使用的列使用了兼容的排序規則,如下所示。tbl_country``cola_countrycode``inner join
IF OBJECT_ID('[dbo].[tbl_country2]') IS NOT NULL DROP TABLE [dbo].[tbl_country2] GO CREATE TABLE [dbo].[tbl_country2] ( [co_code] VARCHAR(2) NOT NULL, [country_id] INT NOT NULL, [co_name] VARCHAR(50) NOT NULL, [co_recruiting] BIT NULL, [co_rank] INT NULL, [co_display] CHAR(10) NULL, [CRM_GuidId] VARCHAR(100) NULL, [cola_countrycode] CHAR(2) COLLATE Latin1_General_CI_AS NULL) ALTER TABLE [dbo].[tbl_country2] ADD CONSTRAINT [PK_TBL_COUNTRY2] PRIMARY KEY CLUSTERED ( [co_code] ASC ) CREATE NONCLUSTERED INDEX I_cola_countrycode ON [dbo].[tbl_country2] ( [cola_countrycode] ASC )
此查詢的主表:
dbo.tbl_UserLogin
此表位於一個名為的數據庫中cola
,其排序規則為Latin1_General_CI_AS
USE [cola] go exec sp_gettabledef 'dbo.tbl_UserLogin' IF OBJECT_ID('[dbo].[tbl_UserLogin]') IS NOT NULL DROP TABLE [dbo].[tbl_UserLogin] GO CREATE TABLE [dbo].[tbl_UserLogin] ( [UserID] NUMERIC(18,0) IDENTITY(1,1) NOT NULL, [UserName] VARCHAR(50) NULL, [Email] VARCHAR(255) NULL, [FirstName] VARCHAR(50) NOT NULL, [middleName] VARCHAR(50) NULL, [LastName] VARCHAR(50) NOT NULL, [CountryCode] VARCHAR(2) NULL, [Gender] CHAR(1) NULL, [PasswordSalt] INT NULL, [ApplicantID] NUMERIC(18,0) NULL, [InterviewerID] NUMERIC(18,0) NULL, [Password] VARCHAR(50) NULL, [DateOfBirth] DATETIME NULL, [ReligionDenom] VARCHAR(30) NULL, [createdOn] DATETIME NOT NULL CONSTRAINT [DF_tbl_UserLogin_createdOn] DEFAULT (getdate()), [RegionId] NUMERIC(18,0) NULL, [faceTimeId] VARCHAR(50) NULL CONSTRAINT [DF__tbl_UserL__faceT__7E1394B9] DEFAULT (NULL), CONSTRAINT [PK_tbl_UserLogin] PRIMARY KEY CLUSTERED ([UserID] asc), CONSTRAINT [uc_Email] UNIQUE NONCLUSTERED ([Email] asc) WITH FILLFACTOR = 100, CONSTRAINT [ck_uniqueApplicantID] CHECK ([dbo].[validateApplicantIDExistance]([applicantID])<=(1)), CONSTRAINT [ck_uniqueInterviewerID] CHECK ([dbo].[validateInterviewerIDExistance]([InterviewerID])<=(1))) GO CREATE NONCLUSTERED INDEX [idx_firstname] ON [dbo].[tbl_UserLogin] ([FirstName] asc) INCLUDE ([ApplicantID], [CountryCode], [Email], [LastName]) WITH FILLFACTOR = 100 CREATE NONCLUSTERED INDEX [idx_interviewerID] ON [dbo].[tbl_UserLogin] ([InterviewerID] asc) WITH FILLFACTOR = 100 CREATE NONCLUSTERED INDEX [idx_lastname] ON [dbo].[tbl_UserLogin] ([LastName] asc) INCLUDE ([ApplicantID], [CountryCode], [Email], [FirstName]) WITH FILLFACTOR = 100 CREATE NONCLUSTERED INDEX [IX_tbl_UserLogin_ApplicantID] ON [dbo].[tbl_UserLogin] ([ApplicantID] asc) INCLUDE ([UserID]) WITH FILLFACTOR = 100
我不知道這個環境中不同數據庫中的不同排序規則是否有特定目的。我不知道我是否可以讓它們都一樣。我試圖避免經歷更改數據庫排序規則的過程。
除此之外,
有什麼辦法可以根據
char or varchar
不同排序規則的列來做這些關節並且仍然使用索引?
關鍵問題是基於排序規則的行順序,尤其是當
VARCHAR
列使用 SQL Server 排序規則時。使用COLLATE
關鍵字更改執行時排序規則不會更改索引中行的物理順序。唯一的修復是:
- 更改
CHAR
/VARCHAR
列的排序規則以使用 Windows 排序規則。(這是最好的選擇)- 用於
COLLATE
強制排序規則為 SQL Server(即以 開頭SQL_
)排序規則。
在使用上面Solomon Rutzky回答的建議編號
2
後,我將原始查詢更改為轉換為COLLATE,如下所示:SQL_%
SET ROWCOUNT 50 SELECT UL.* FROM COLA.dbo.tbl_UserLogin ul INNER JOIN CABrochure.dbo.tbl_country co ON ul.CountryCode COLLATE SQL_Latin1_General_CP1_CI_AS = co.cola_countrycode COLLATE SQL_Latin1_General_CP1_CI_AS SELECT UL.* FROM COLA.dbo.tbl_UserLogin ul INNER JOIN CRMReferences.dbo.tbl_country2 co ON ul.CountryCode = co.cola_countrycode SET ROWCOUNT 0
我得到了這個更好的執行計劃,它可以進行索引搜尋 ,如下圖所示: