次のクエリを実行しています。
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
テーブルと2番目のテーブルCRMReferences.dbo.tbl_country2
の唯一の違いは、collation
です。
CRMReferences.dbo.tbl_country2
テーブルと同じtbl_country
を作成(およびすべてのデータを入力)しました[〜#〜] but [〜#〜]以下のように、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
このテーブルは、照合がLatin1_General_CI_AS
であるcola
というデータベースにあります。
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
を使用した後、元のクエリを次のようにSQL_%
COLLATEに変換するように変更しました。
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
私はこれを手に入れました インデックスシークを実行するはるかに優れた実行プラン 下の図でわかるように: