Tôi hy vọng hai số SELECT
sẽ có cùng một kế hoạch thực hiện và hiệu suất. Vì có một ký tự đại diện hàng đầu trên LIKE
, tôi mong đợi quét chỉ mục. Khi tôi chạy điều này và xem xét các kế hoạch, SELECT
hoạt động như mong đợi (với một lần quét). Nhưng kế hoạch SELECT
thứ hai cho thấy chỉ mục tìm kiếm và chạy nhanh hơn gấp 20 lần.Cách LIKE '% ...' có thể tìm kiếm chỉ mục như thế nào?
Code:
-- Uses index scan, as expected:
SELECT 1
FROM AccountAction
WHERE AccountNumber LIKE '%441025586401'
-- Uses index seek somehow, and runs much faster:
declare @empty VARCHAR(30) = ''
SELECT 1
FROM AccountAction
WHERE AccountNumber LIKE '%441025586401' + @empty
Câu hỏi:
Làm thế nào để SQL Server sử dụng một chỉ mục tìm kiếm khi mô hình bắt đầu với một ký tự đại diện?
Bonus câu hỏi:
Tại sao concatenating một sự thay đổi chuỗi rỗng/cải thiện kế hoạch thực hiện?
chi tiết:
- Có một chỉ số không clustered trên
Accounts.AccountNumber
- Có các chỉ số khác, nhưng cả hai tìm kiếm và quét là trên chỉ số này.
- Cột
Accounts.AccountNumber
là một nullablevarchar(30)
- Máy chủ là SQL Server 2012
Bảng và chỉ số định nghĩa:
CREATE TABLE [updatable].[AccountAction](
[ID] [int] IDENTITY(1,1) NOT NULL,
[AccountNumber] [varchar](30) NULL,
[Utility] [varchar](9) NOT NULL,
[SomeData1] [varchar](10) NOT NULL,
[SomeData2] [varchar](200) NULL,
[SomeData3] [money] NULL,
--...
[Created] [datetime] NULL,
CONSTRAINT [PK_Account] PRIMARY KEY NONCLUSTERED
(
[ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
CREATE NONCLUSTERED INDEX [IX_updatable_AccountAction_AccountNumber_UtilityCode_ActionTypeCd] ON [updatable].[AccountAction]
(
[AccountNumber] ASC,
[Utility] ASC
)
INCLUDE ([SomeData1], [SomeData2], [SomeData3]) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
CREATE CLUSTERED INDEX [CIX_Account] ON [updatable].[AccountAction]
(
[Created] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
LƯU Ý: Dưới đây là kế hoạch thực hiện thực tế cho hai truy vấn. Tên của các đối tượng hơi khác so với mã ở trên vì tôi đang cố giữ cho câu hỏi đơn giản.
là có sự khác biệt trong thực hiện thực tế hoặc chỉ trong kế hoạch dự toán? –
@GordonLinoff Số phiên bản SQL Server 2012 là 11, 2008 R2: 10.5, 2008: 10, v.v. – swasheck
Tôi không biết tầm quan trọng của nó, nhưng các truy vấn mà bạn thực sự chạy là 'LIKE '% 441025586401%'' , với ký tự đại diện ở phần bắt đầu và kết thúc – Lamak