Tôi đang cố gắng cải thiện truy vấn (phụ) này là một phần của truy vấn lớn hơn:
select SUM(isnull(IP.Q, 0)) as Q,
IP.OPID
from IP
inner join I
on I.ID = IP.IID
where
IP.Deleted=0 and
(I.Status > 0 AND I.Status <= 19)
group by IP.OPID
Sentry Plan Explorer đã chỉ ra một số Tra cứu khóa tương đối đắt tiền cho bảng dbo. [I] được thực hiện bởi truy vấn trên.
Bảng dbo.I
CREATE TABLE [dbo].[I] (
[ID] UNIQUEIDENTIFIER NOT NULL,
[OID] UNIQUEIDENTIFIER NOT NULL,
[] UNIQUEIDENTIFIER NOT NULL,
[] UNIQUEIDENTIFIER NOT NULL,
[] UNIQUEIDENTIFIER NULL,
[] UNIQUEIDENTIFIER NOT NULL,
[] CHAR (3) NOT NULL,
[] CHAR (3) DEFAULT ('EUR') NOT NULL,
[] DECIMAL (18, 8) DEFAULT ((1)) NOT NULL,
[] CHAR (10) NOT NULL,
[] DECIMAL (18, 8) DEFAULT ((1)) NOT NULL,
[] DATETIME DEFAULT (getdate()) NOT NULL,
[] VARCHAR (35) NULL,
[] NVARCHAR (100) NOT NULL,
[] NVARCHAR (100) NULL,
[] NTEXT NULL,
[] NTEXT NULL,
[] NTEXT NULL,
[] NTEXT NULL,
[Status] INT DEFAULT ((0)) NOT NULL,
[] DECIMAL (18, 2) NOT NULL,
[] DECIMAL (18, 2) NOT NULL,
[] DECIMAL (18, 2) NOT NULL,
[] DATETIME DEFAULT (getdate()) NULL,
[] DATETIME NULL,
[] NTEXT NULL,
[] NTEXT NULL,
[] TINYINT DEFAULT ((0)) NOT NULL,
[] DATETIME NULL,
[] VARCHAR (50) NULL,
[] DATETIME DEFAULT (getdate()) NOT NULL,
[] VARCHAR (50) NOT NULL,
[] DATETIME NULL,
[] VARCHAR (50) NULL,
[] ROWVERSION NOT NULL,
[] DATETIME NULL,
[] INT NULL,
[] TINYINT DEFAULT ((0)) NOT NULL,
[] UNIQUEIDENTIFIER NULL,
[] TINYINT DEFAULT ((0)) NOT NULL,
[] TINYINT DEFAULT ((0)) NOT NULL,
[] NVARCHAR (50) NULL,
[] TINYINT DEFAULT ((0)) NOT NULL,
[] UNIQUEIDENTIFIER NULL,
[] UNIQUEIDENTIFIER NULL,
[] TINYINT DEFAULT ((0)) NOT NULL,
[] TINYINT DEFAULT ((0)) NOT NULL,
[] UNIQUEIDENTIFIER NULL,
[] DECIMAL (18, 2) NULL,
[] DECIMAL (18, 2) NULL,
[] DECIMAL (18, 2) DEFAULT ((0)) NOT NULL,
[] UNIQUEIDENTIFIER NULL,
[] DATETIME NULL,
[] DATETIME NULL,
[] VARCHAR (35) NULL,
[] DECIMAL (18, 2) DEFAULT ((0)) NOT NULL,
CONSTRAINT [PK_I] PRIMARY KEY NONCLUSTERED ([ID] ASC) WITH (FILLFACTOR = 90),
CONSTRAINT [FK_I_O] FOREIGN KEY ([OID]) REFERENCES [dbo].[O] ([ID]),
CONSTRAINT [FK_I_Status] FOREIGN KEY ([Status]) REFERENCES [dbo].[T_Status] ([Status])
);
GO
CREATE CLUSTERED INDEX [CIX_Invoice]
ON [dbo].[I]([OID] ASC) WITH (FILLFACTOR = 90);
Bảng dbo.IP
CREATE TABLE [dbo].[IP] (
[ID] UNIQUEIDENTIFIER DEFAULT (newid()) NOT NULL,
[IID] UNIQUEIDENTIFIER NOT NULL,
[OID] UNIQUEIDENTIFIER NOT NULL,
[Deleted] TINYINT DEFAULT ((0)) NOT NULL,
[] UNIQUEIDENTIFIER NULL,
[] UNIQUEIDENTIFIER NULL,
[] UNIQUEIDENTIFIER NULL,
[] UNIQUEIDENTIFIER NULL,
[] UNIQUEIDENTIFIER NULL,
[]UNIQUEIDENTIFIER NULL,
[] UNIQUEIDENTIFIER NULL,
[] UNIQUEIDENTIFIER NULL,
[] INT NOT NULL,
[] VARCHAR (35) NULL,
[] NVARCHAR (100) NOT NULL,
[] NTEXT NULL,
[] DECIMAL (18, 4) DEFAULT ((0)) NOT NULL,
[] NTEXT NULL,
[] NTEXT NULL,
[] DECIMAL (18, 4) DEFAULT ((0)) NOT NULL,
[] DECIMAL (18, 4) DEFAULT ((0)) NOT NULL,
[] DECIMAL (4, 2) NOT NULL,
[] INT DEFAULT ((1)) NOT NULL,
[] DATETIME DEFAULT (getdate()) NOT NULL,
[] VARCHAR (50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
[] DATETIME NULL,
[] VARCHAR (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
[] ROWVERSION NOT NULL,
[] INT DEFAULT ((1)) NOT NULL,
[] DATETIME NULL,
[] UNIQUEIDENTIFIER NULL,
[] DECIMAL (18, 4) DEFAULT ((1)) NOT NULL,
[] DECIMAL (18, 4) DEFAULT ((1)) NOT NULL,
[] INT DEFAULT ((0)) NOT NULL,
[] UNIQUEIDENTIFIER NULL,
[] UNIQUEIDENTIFIER NULL,
[] UNIQUEIDENTIFIER NULL,
[] UNIQUEIDENTIFIER NULL,
[]UNIQUEIDENTIFIER NULL,
[]NVARCHAR (35) NULL,
[] VARCHAR (35) NULL,
[] NVARCHAR (35) NULL,
[] NVARCHAR (35) NULL,
[] NVARCHAR (35) NULL,
[] NVARCHAR (35) NULL,
[] NVARCHAR (35) NULL,
[] NVARCHAR (35) NULL,
[] UNIQUEIDENTIFIER NULL,
[] VARCHAR (12) NULL,
[] VARCHAR (4) NULL,
[] NVARCHAR (50) NULL,
[] NVARCHAR (50) NULL,
[] VARCHAR (35) NULL,
[] UNIQUEIDENTIFIER NULL,
[] UNIQUEIDENTIFIER NULL,
[] TINYINT DEFAULT ((0)) NOT NULL,
[] UNIQUEIDENTIFIER NULL,
[] TINYINT DEFAULT ((0)) NOT NULL,
[] TINYINT DEFAULT ((0)) NOT NULL,
[] NVARCHAR (50) NULL,
[] TINYINT DEFAULT ((0)) NOT NULL,
[] DECIMAL (18, 2) NULL,
[]TINYINT DEFAULT ((1)) NOT NULL,
[] UNIQUEIDENTIFIER NULL,
[] UNIQUEIDENTIFIER NULL,
[] UNIQUEIDENTIFIER NULL,
[] TINYINT DEFAULT ((1)) NOT NULL,
CONSTRAINT [PK_IP] PRIMARY KEY NONCLUSTERED ([ID] ASC) WITH (FILLFACTOR = 90),
CONSTRAINT [FK_IP_I] FOREIGN KEY ([IID]) REFERENCES [dbo].[I] ([ID]) ON DELETE CASCADE NOT FOR REPLICATION,
CONSTRAINT [FK_IP_XType] FOREIGN KEY ([XType]) REFERENCES [dbo].[xTYPE] ([Value]) NOT FOR REPLICATION
);
GO
CREATE CLUSTERED INDEX [IX_IP_CLUST]
ON [dbo].[IP]([IID] ASC) WITH (FILLFACTOR = 90);
Bảng "I" có khoảng 100.000 hàng, chỉ mục được nhóm có 9.386 trang.
IP bảng là "con" - bảng của I và có khoảng 175.000 hàng.
Tôi đã cố gắng thêm một chỉ mục mới theo quy tắc thứ tự cột chỉ mục: "WHERE-THAM GIA-ĐẶT HÀNG- (CHỌN)"
để giải quyết các tra cứu chính và tạo chỉ mục tìm kiếm:
CREATE NONCLUSTERED INDEX [IX_I_Status_1]
ON [dbo].[Invoice]([Status], [ID])
Các truy vấn trích xuất ngay lập tức sử dụng chỉ mục này. Nhưng truy vấn lớn hơn ban đầu nó là một phần của, không. Nó thậm chí không sử dụng nó khi tôi buộc nó sử dụng VỚI (INDEX (IX_I_Status_1)).
Sau một thời gian, tôi quyết định thử một chỉ mục mới khác và thay đổi thành thứ tự của các cột được lập chỉ mục:
CREATE NONCLUSTERED INDEX [IX_I_Status_2]
ON [dbo].[Invoice]([ID], [Status])
CHÀO! Chỉ mục này được sử dụng bởi truy vấn trích xuất và truy vấn lớn hơn!
Sau đó, tôi đã so sánh các thống kê IO được trích xuất bằng cách buộc nó sử dụng [IX_I_Status_1] và [IX_I_Status_2]:
Kết quả [IX_I_Status_1]:
Table 'I'. Scan count 5, logical reads 636, physical reads 16, read-ahead reads 574
Table 'IP'. Scan count 5, logical reads 1134, physical reads 11, read-ahead reads 1040
Table 'Worktable'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0
Kết quả [IX_I_Status_2]:
Table 'I'. Scan count 1, logical reads 615, physical reads 6, read-ahead reads 631
Table 'IP'. Scan count 1, logical reads 1024, physical reads 5, read-ahead reads 1040
Table 'Worktable'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0
OK, tôi có thể hiểu rằng truy vấn quái vật khổng lồ có thể quá phức tạp để khiến máy chủ SQL bắt được kế hoạch thực hiện lý tưởng và có thể bỏ lỡ chỉ mục mới của tôi. Nhưng tôi không hiểu tại sao chỉ mục [IX_I_Status_2] dường như phù hợp hơn và hiệu quả hơn cho truy vấn.
Vì truy vấn đầu tiên của tất cả các bộ lọc bảng I theo cột STATUS và sau đó kết hợp với IP bảng, tôi không hiểu tại sao [IX_I_Status_2] tốt hơn và được sử dụng bởi Sql Server thay vì [IX_I_Status_1]?