Các hoạt động tổng hợp trên View Ignores Index [đã đóng]


8

Kịch bản

Ngày xửa ngày xưa, có một cơ sở dữ liệu Staging tại một công ty nhỏ đang tham gia vào quy trình ETL, hoạt động như một danh mục nhận các định dạng khác nhau của các tệp từ một số nguồn của bên thứ ba. E được xử lý thông qua các gói DTS, với một vài cấu trúc điều khiển để kiểm tra hoặc kiểm soát, nhưng được coi là "Đủ tốt" và cho tất cả các ý định và mục đích, nó đã được.

Dữ liệu được cung cấp bởi phần E được dành cho tiêu dùng bởi một ứng dụng đơn lẻ, được phát triển và quản lý bởi một số ít lập trình viên trẻ và có khả năng. Mặc dù thiếu kinh nghiệm hoặc kiến ​​thức về các kỹ thuật lưu trữ dữ liệu thời đó, họ đã đặt ra và tạo ra các quy trình T và L của riêng họ từ mã ứng dụng. Rực rỡ, những kỹ sư phần mềm non trẻ này đã phát minh ra thứ mà người ngoài có thể gọi là "bánh xe kém lý tưởng", nhưng với "Mức độ đủ tốt" như một mức độ dịch vụ hiện tại, họ có thể cung cấp một khung hoạt động.

Trong một thời gian, tất cả đều tốt trong vương quốc kết hợp chặt chẽ, với danh mục Staging đang ăn mừng dữ liệu của hàng tá bên thứ ba, lần lượt được ứng dụng cho ăn. Khi ứng dụng phát triển, sự thèm ăn của nó cũng tăng theo, nhưng với các nhà phát triển hiệp sĩ trắng khéo léo đứng theo dõi hệ thống, những sự thèm ăn này đã được giải quyết nhanh chóng và trong nhiều trường hợp, thậm chí là tốt.

Nhưng thời kỳ hoàng kim không thể kéo dài mãi mãi, dĩ nhiên. Với sự thịnh vượng được cấp bởi ứng dụng thành công, doanh nghiệp ngày càng phát triển. Khi nó phát triển, môi trường và ứng dụng Staging buộc phải phát triển cùng với nó. Đối với tất cả sự cảnh giác của họ, chỉ một số ít các nhà phát triển anh hùng không thể theo kịp việc duy trì hệ thống mở rộng hiện nay và người tiêu dùng đã được hưởng dữ liệu của họ. Không còn là vấn đề họ cần hoặc thậm chí muốn, nhưng dân chúng cảm thấy rằng họ chỉ đơn giản xứng đáng với điều đó, đòi hỏi nhiều hơn nữa.

Được trang bị ít hơn nhiều so với các kho chứa đầy swag, doanh nghiệp đã tiếp cận thị trường, thuê các nhà phát triển và quản trị viên để giúp hỗ trợ hệ thống ngày càng phát triển. Lính đánh thuê của mọi ethos đổ xô đến công ty, nhưng với sự tăng trưởng này đã phát triển rất ít theo cách hướng dẫn chuyên gia có sẵn. Các nhà phát triển và quản trị viên mới đấu tranh để hiểu được sự phức tạp của bộ sản xuất tại nhà, cho đến khi sự thất vọng dẫn đến tất cả chiến tranh. Mỗi bộ phận bắt đầu cố gắng giải quyết mọi vấn đề một mình, làm nhiều việc để chống lại nhau hơn là làm việc với nhau. Một dự án hoặc sáng kiến ​​sẽ được thực hiện theo nhiều cách khác nhau, mỗi cách hơi khác so với kế tiếp. Sự căng thẳng của tất cả đã chứng tỏ là quá nhiều đối với một số hiệp sĩ trắng và khi họ ngã xuống, đế chế sụp đổ. Chẳng mấy chốc, hệ thống đã bị xáo trộn,

Mặc dù đã chuyển đổi các lĩnh vực hứa hẹn thành mã spaghetti đẫm máu, công ty vẫn chịu đựng. Rốt cuộc, đó là "Đủ tốt."

Các thách thức

Một vài thay đổi chế độ và thuê mướn sau đó, tôi thấy mình đang làm việc cho công ty. Đã nhiều năm kể từ các cuộc chiến lớn, nhưng thiệt hại gây ra vẫn rất rõ ràng. Tôi đã quản lý để giải quyết một số điểm yếu trong phần E của hệ thống và thêm một số bảng điều khiển trong khi dưới vỏ bọc nâng cấp các gói DTS lên SSIS, hiện đang được một số chuyên gia lưu trữ dữ liệu thực tế sử dụng khi chúng tạo ra bình thường và ghi lại sự thay thế T và L.

Rào cản đầu tiên là nhập dữ liệu từ các tệp của bên thứ ba theo cách không cắt bớt các giá trị hoặc thay đổi các loại dữ liệu gốc, nhưng cũng bao gồm một số phím điều khiển để tải lại và thanh trừng. Đây là tất cả tốt và tốt, nhưng các ứng dụng cần thiết để có thể truy cập các bảng mới này một cách liền mạch, minh bạch. Gói DTS có thể điền vào bảng, sau đó ứng dụng sẽ đọc trực tiếp. Việc nâng cấp SSIS cần phải được thực hiện song song vì lý do QA, nhưng các gói mới này bao gồm các khóa điều khiển khác nhau và cũng tận dụng sơ đồ phân vùng, chưa kể các thay đổi siêu dữ liệu thực tế có thể đủ để đảm bảo một bảng mới hoàn toàn, vì vậy bảng mới đã được sử dụng cho các gói SSIS mới.

Với việc nhập dữ liệu đáng tin cậy hiện đang hoạt động và được sử dụng bởi nhóm kho, thử thách thực sự là phục vụ dữ liệu mới cho các ứng dụng truy cập trực tiếp vào môi trường Staging, với tác động tối thiểu (còn gọi là "Không") đối với mã ứng dụng. Đối với điều này, tôi đã được bầu vào quan điểm sử dụng, đổi tên một bảng như dbo.DailyTransactionđể dbo.DailyTranscation_LEGACYvà tái sử dụng các dbo.DailyTransactiontên đối tượng cho một cái nhìn, mà hiệu quả chỉ Selects tất cả mọi thứ từ bây giờLEGACYbảng chỉ định. Do việc tải lại các năm dữ liệu trong các bảng này không phải là một lựa chọn theo quan điểm của doanh nghiệp, vì các bảng được phân vùng và phân vùng SSIS mới được đưa vào sản xuất, việc nhập DTS cũ bị tắt và các ứng dụng cần phải có khả năng truy cập dữ liệu mới trong các bảng mới là tốt. Tại thời điểm này, các khung nhìn được cập nhật để chọn dữ liệu từ các bảng mới ( dbo.DailyTransactionCompleteví dụ: chẳng hạn) khi có sẵn và chọn từ các bảng kế thừa khi không có.

Trong thực tế, một cái gì đó như sau đây đang được thực hiện:

CREATE VIEW dbo.DailyTransaction
AS  SELECT  DailyTransaction_PK, FileDate, Foo
    FROM    dbo.DailyTransactionComplete
    UNION ALL
    SELECT  DailyTransaction_PK, FileDate, Foo
    FROM    dbo.DailyTransaction_LEGACY l
    WHERE NOT EXISTS (  SELECT  1
                        FROM    dbo.DailyTransactionComplete t
                        WHERE   t.FileDate = l.FileDate );

Mặc dù về mặt logic, điều này hoàn toàn không hoạt động tốt trong một số trường hợp tổng hợp, thường dẫn đến một kế hoạch thực hiện thực hiện quét chỉ mục đầy đủ đối với dữ liệu trong bảng kế thừa. Điều này có thể tốt cho vài chục triệu hồ sơ, nhưng không nhiều cho vài chục trăm triệu hồ sơ. Vì thực tế sau này, tôi đã phải dùng đến ... "sáng tạo", dẫn tôi đến việc tạo ra một cái nhìn được lập chỉ mục.

Đây là trường hợp ít thử nghiệm tôi đã thiết lập, bao gồm các FileDatephím điều khiển đã được chuyển đến các tương thích Data Warehouse DateCode_FKcổng cho minh họa cách hoàn toàn chút tôi quan tâm đến các truy vấn đối với các bảng mới là sargable trong thời gian tới:

USE tempdb;
GO

SET NOCOUNT ON;
GO

IF NOT EXISTS ( SELECT  1
                FROM    sys.objects
                WHERE   name = 'DailyTransaction_LEGACY'
                    AND type = 'U' )
BEGIN
    --DROP TABLE dbo.DailyTransaction_LEGACY;
    CREATE TABLE dbo.DailyTransaction_LEGACY
    (
        DailyTransaction_PK         BIGINT IDENTITY( 1, 1 ) NOT NULL,
        FileDate                    DATETIME NOT NULL,
        Foo                         INT NOT NULL
    );

    INSERT INTO dbo.DailyTransaction_LEGACY ( FileDate, Foo )
    SELECT  DATEADD( DAY, ( 1 - ROW_NUMBER() 
                OVER( ORDER BY so1.object_id ) - 800 ) % 1000, 
                CONVERT( DATE, GETDATE() ) ),
            so1.object_id % 1000 + so2.object_id % 1000
    FROM    sys.all_objects so1
    CROSS JOIN sys.all_objects so2;

    ALTER TABLE dbo.DailyTransaction_LEGACY
    ADD CONSTRAINT PK__DailyTrainsaction
        PRIMARY KEY CLUSTERED ( DailyTransaction_PK )
    WITH ( DATA_COMPRESSION = PAGE, FILLFACTOR = 100 );
END;
GO

IF NOT EXISTS ( SELECT  1
                FROM    sys.objects
                WHERE   name = 'DailyTransactionComplete'
                    AND type = 'U' )
BEGIN
    --DROP TABLE dbo.DailyTransactionComplete;
    CREATE TABLE dbo.DailyTransactionComplete
    (
        DailyTransaction_PK            BIGINT IDENTITY( 1, 1 ) NOT NULL,
        DateCode_FK                    INTEGER NOT NULL,
        Foo                            INTEGER NOT NULL
    );

    INSERT INTO dbo.DailyTransactionComplete ( DateCode_FK, Foo )
    SELECT  TOP 100000
            CONVERT( INTEGER, CONVERT( VARCHAR( 8 ), DATEADD( DAY, 
                ( 1 - ROW_NUMBER() OVER( ORDER BY so1.object_id ) ) % 100, 
                GETDATE() ), 112 ) ),
            so1.object_id % 1000
    FROM    sys.all_objects so1
    CROSS JOIN sys.all_objects so2;

    ALTER TABLE dbo.DailyTransactionComplete
    ADD CONSTRAINT PK__DailyTransaction
        PRIMARY KEY CLUSTERED ( DateCode_FK, DailyTransaction_PK )
    WITH ( DATA_COMPRESSION = PAGE, FILLFACTOR = 100 );        
END;
GO

Trên hộp cát cục bộ của tôi, ở trên giúp tôi có một bảng kế thừa với khoảng 4,4 triệu hàng và một bảng mới chứa 0,1 triệu hàng, với một số giá trị DateCode_FK/ chồng chéo FileDate.

Bảng MAX( FileDate )so với bảng kế thừa không có chỉ mục bổ sung nào chạy về những gì tôi mong đợi.

SET STATISTICS IO, TIME ON;

DECLARE @ConsumeOutput        DATETIME;
SELECT  @ConsumeOutput = MAX( FileDate )
FROM    dbo.DailyTransaction_LEGACY;

SET STATISTICS IO, TIME OFF;
GO

Bảng 'DailyTransaction_LEGACY'. Quét số 1, đọc logic 9228, đọc vật lý 0, đọc trước 0, đọc logic 0, đọc vật lý lob 0, đọc trước đọc 0, đọc trước 0.

Thời gian thực hiện máy chủ SQL: Thời gian CPU = 889 ms, thời gian trôi qua = 886 ms.

Chỉ số cụm, di sản

Tung một chỉ số đơn giản trên bàn làm cho mọi thứ tốt hơn nhiều. Vẫn là quét, nhưng quét một bản ghi thay vì 4,4 triệu bản ghi. Tôi rất tuyệt với điều đó.

CREATE NONCLUSTERED INDEX IX__DailyTransaction__FileDate
    ON    dbo.DailyTransaction_LEGACY ( FileDate );

SET STATISTICS IO, TIME ON;

DECLARE @ConsumeOutput        DATETIME;
SELECT  @ConsumeOutput = MAX( FileDate )
FROM    dbo.DailyTransaction_LEGACY;

SET STATISTICS IO, TIME OFF;
GO

Thời gian phân tích và biên dịch SQL Server: Thời gian CPU = 0 ms, thời gian trôi qua = 1 ms. Bảng 'DailyTransaction_LEGACY'. Quét số 1, đọc logic 3, đọc vật lý 0, đọc trước đọc 0, đọc logic 0, đọc vật lý lob 0, đọc trước đọc 0, đọc trước 0.

Thời gian thực thi máy chủ SQL: Thời gian CPU = 0 ms, thời gian trôi qua = 0 ms.

Chỉ mục không phân cụm, Di sản

Và bây giờ, tạo chế độ xem để các nhà phát triển không phải thay đổi bất kỳ mã nào vì đó rõ ràng sẽ là ngày tận thế như chúng ta biết. Một thảm họa của các loại.

IF NOT EXISTS ( SELECT  1
                FROM    sys.objects
                WHERE   name = 'DailyTransaction'
                    AND type = 'V' )
BEGIN
    EXEC( 'CREATE VIEW dbo.DailyTransaction AS SELECT x = 1;' );
END;
GO

ALTER VIEW dbo.DailyTransaction
AS  SELECT  DailyTransaction_PK, FileDate = CONVERT( 
                DATETIME, CONVERT( VARCHAR( 8 ), DateCode_FK ), 112 ), Foo
    FROM    dbo.DailyTransactionComplete
    UNION ALL    
    SELECT  DailyTransaction_PK, FileDate, Foo
    FROM    dbo.DailyTransaction_LEGACY l
    WHERE   NOT EXISTS (    SELECT  1
                            FROM    dbo.DailyTransactionComplete t
                            WHERE   CONVERT( DATETIME, CONVERT( VARCHAR( 8 ),
                                        t.DateCode_FK ), 112 ) = l.FileDate );
GO

Đúng, truy vấn phụ rất tệ, nhưng đây không phải là vấn đề và có lẽ tôi chỉ đơn giản là tạo một cột được tính toán bền bỉ và ném một chỉ mục cho mục đích đó khi vấn đề thực sự được giải quyết. Vì vậy, không có thêm ado,

Vấn đề

SET STATISTICS IO, TIME ON;

DECLARE @ConsumeOutput1        DATETIME;
SELECT  @ConsumeOutput1 = MAX( FileDate )
FROM    dbo.DailyTransaction;

SET STATISTICS IO, TIME OFF;
GO

Thời gian phân tích và biên dịch SQL Server: Thời gian CPU = 0 ms, thời gian trôi qua = 4 ms. Bảng 'DailyTransaction_LEGACY'. Quét số 1, đọc logic 11972, đọc vật lý 0, đọc trước đọc 0, đọc logic 0, đọc vật lý lob 0, đọc trước đọc trước 0. Bảng 'Bàn làm việc'. Quét số 0, đọc logic 0, đọc vật lý 0, đọc trước đọc 0, đọc logic 0, đọc vật lý lob 0, đọc trước đọc trước 0. Bảng 'Workfile'. Quét số 0, đọc logic 0, đọc vật lý 0, đọc trước đọc 0, đọc logic 0, đọc vật lý 0, đọc đọc trước 0, đọc bảng "DailyTransactionComplete '. Quét số 2, đọc logic 620, đọc vật lý 0, đọc trước đọc 0, đọc logic 0, đọc vật lý lob 0, đọc trước đọc 0, đọc trước 0.

Thời gian thực thi máy chủ SQL: Thời gian CPU = 983 ms, thời gian trôi qua = 983 ms.

Xem kế hoạch

Ồ tôi hiểu rồi, Sql Server đang cố nói với tôi rằng những gì tôi đang làm là ngu ngốc. Trong khi tôi phần lớn đồng ý, điều đó không thay đổi tình trạng khó khăn của tôi. Điều này thực sự hoạt động rực rỡ cho các truy vấn nơi FileDatetrên dbo.DailyTransactionxem được bao gồm trong các vị, nhưng trong khi MAXkế hoạch là đủ xấu, các TOPkế hoạch gửi toàn bộ điều chạy về phía nam. Nam thực.

SET STATISTICS IO, TIME ON;

SELECT  TOP 10 FileDate
FROM    dbo.DailyTransaction
GROUP BY FileDate 
ORDER BY FileDate DESC

SET STATISTICS IO, TIME OFF;
GO

Bảng 'DailyTransactionComplete'. Quét số 2, đọc logic 1800110, đọc vật lý 0, đọc trước đọc 0, đọc logic 0, đọc vật lý lob 0, đọc trước đọc trước 0. Bảng 'DailyTransaction_LEGACY'. Quét số 1, đọc logic 1254, đọc vật lý 0, đọc trước đọc 0, đọc logic 0, đọc vật lý lob 0, đọc trước đọc trước 0. Bảng 'Worktable'. Quét số 0, đọc logic 0, đọc vật lý 0, đọc trước đọc 0, đọc logic 0, đọc vật lý lob 0, đọc trước đọc trước 0. Bảng 'Workfile'. Quét số 0, đọc logic 0, đọc vật lý 0, đọc trước đọc 0, đọc logic 0, đọc vật lý lob 0, đọc trước đọc 0, đọc trước 0.

Thời gian thực thi của máy chủ SQL: Thời gian CPU = 109559 ms, thời gian đã trôi qua = 109664 ms.

Hàng đầu

Tôi đã đề cập đến việc "sáng tạo" trước đó, có lẽ là sai lệch. Điều tôi muốn nói là "ngu ngốc hơn", vì vậy những nỗ lực của tôi để làm cho chế độ xem này hoạt động trong các hoạt động tổng hợp là tạo các khung nhìn trên dbo.DailyTransactionCompletedbo.DailyTransaction_LEGACYcác bảng, liên kết lược đồ và lập chỉ mục cho khung nhìn sau, sau đó sử dụng các khung nhìn đó trong một khung nhìn khác với một NOEXPANDgợi ý trên quan điểm di sản. Mặc dù hiện tại nó ít nhiều hoạt động cho những gì nó cần làm, tôi thấy toàn bộ "giải pháp" khá khó chịu, lên đến đỉnh điểm với những điều sau:

IF NOT EXISTS ( SELECT  1
                FROM    sys.objects
                WHERE   name = 'v_DailyTransactionComplete'
                    AND type = 'V' )
BEGIN
    EXEC( 'CREATE VIEW dbo.v_DailyTransactionComplete AS SELECT x = 1;' );
END;
GO

ALTER VIEW dbo.v_DailyTransactionComplete
AS  SELECT  DailyTransaction_PK, FileDate = CONVERT( DATETIME, 
                CONVERT( VARCHAR( 8 ), DateCode_FK ), 112 ), 
            Foo
    FROM    dbo.DailyTransactionComplete;
GO

IF NOT EXISTS ( SELECT  1
                FROM    sys.objects
                WHERE   name = 'v_DailyTransaction_LEGACY'
                    AND type = 'V' )
BEGIN
    EXEC( 'CREATE VIEW dbo.v_DailyTransaction_LEGACY AS SELECT x = 1;' );
END;
GO

ALTER VIEW dbo.v_DailyTransaction_LEGACY
WITH SCHEMABINDING
AS  SELECT  l.DailyTransaction_PK,
            l.FileDate,
            l.Foo,
            CountBig = COUNT_BIG( * )
    FROM    dbo.DailyTransaction_LEGACY l
    INNER JOIN dbo.DailyTransactionComplete n
        ON  l.FileDate <> CONVERT( DATETIME, CONVERT( VARCHAR( 8 ), 
                n.DateCode_FK ), 112 )
    GROUP BY l.DailyTransaction_PK,
            l.FileDate,
            l.Foo;
GO

CREATE UNIQUE CLUSTERED INDEX CI__v_DailyTransaction_LEGACY
    ON dbo.v_DailyTransaction_LEGACY ( FileDate, DailyTransaction_PK )
WITH ( DATA_COMPRESSION = PAGE, FILLFACTOR = 80 );
GO

IF NOT EXISTS ( SELECT  1
                FROM    sys.objects
                WHERE   name = 'DailyTransaction'
                    AND type = 'V' )
BEGIN
    EXEC( 'CREATE VIEW dbo.DailyTransaction AS SELECT x = 1;' );
END;
GO

ALTER VIEW dbo.DailyTransaction
AS  SELECT  DailyTransaction_PK, FileDate, Foo
    FROM    dbo.v_DailyTransactionComplete
    UNION ALL    
    SELECT  DailyTransaction_PK, FileDate, Foo
    FROM    dbo.v_DailyTransaction_LEGACY WITH ( NOEXPAND );
GO

Việc buộc trình tối ưu hóa sử dụng chỉ mục được cung cấp bởi chế độ xem được lập chỉ mục sẽ khiến các vấn đề MAXTOPvấn đề biến mất, nhưng phải có một cách tốt hơn để đạt được những gì tôi đang cố gắng thực hiện ở đây. Hoàn toàn bất kỳ đề nghị / la mắng sẽ được rất nhiều đánh giá cao !!

SET STATISTICS IO, TIME ON;

DECLARE @ConsumeOutput1        DATETIME;
SELECT  @ConsumeOutput1 = MAX( FileDate )
FROM    dbo.DailyTransaction;

SET STATISTICS IO, TIME OFF;
GO

Bảng 'v_DailyTransaction_LEGACY'. Quét số 1, đọc logic 3, đọc vật lý 0, đọc trước đọc 0, đọc logic 0, đọc vật lý lob 0, đọc trước đọc trước 0. Bảng 'DailyTransactionComplete'. Quét số 1, đọc logic 310, đọc vật lý 0, đọc trước 0, đọc logic 0, đọc vật lý lob 0, đọc trước đọc 0, đọc trước 0.

Thời gian thực thi máy chủ SQL: Thời gian CPU = 31 ms, thời gian trôi qua = 36 ms.

SET STATISTICS IO, TIME ON;

DECLARE @ConsumeOutput1        DATETIME;
SELECT  TOP 10 @ConsumeOutput1 = FileDate
FROM    dbo.DailyTransaction
GROUP BY FileDate 
ORDER BY FileDate DESC

SET STATISTICS IO, TIME OFF;
GO

Bảng 'v_DailyTransaction_LEGACY'. Quét số 1, đọc logic 101, đọc vật lý 0, đọc trước đọc 0, đọc logic 0, đọc vật lý lob 0, đọc trước đọc trước 0. Bảng 'Worktable'. Quét số 0, đọc logic 0, đọc vật lý 0, đọc trước đọc 0, đọc logic 0, đọc vật lý lob 0, đọc trước đọc trước 0. Bảng 'Workfile'. Quét số 0, đọc logic 0, đọc vật lý 0, đọc trước đọc 0, đọc logic 0, đọc vật lý 0, đọc đọc trước 0, đọc bảng "DailyTransactionComplete '. Quét số 1, đọc logic 310, đọc vật lý 0, đọc trước 0, đọc logic 0, đọc vật lý lob 0, đọc trước đọc 0, đọc trước 0.

Thời gian thực thi máy chủ SQL: Thời gian CPU = 63 ms, thời gian trôi qua = 66 ms.

TL; DR:

Giúp tôi hiểu những gì tôi cần làm để thực hiện các truy vấn tổng hợp trên chế độ xem đầu tiên tôi đã đề cập chạy trong khoảng thời gian hợp lý với việc sử dụng tài nguyên I / O hợp lý.


3
Chế độ xem không được lập chỉ mục không lưu trữ bất kỳ dữ liệu nào và bạn không thể lập chỉ mục chế độ xem với các truy vấn con, hiệp hội, v.v. Tôi nghĩ rằng bạn cần xem xét cụ thể hóa dữ liệu theo một cách khác, chẳng hạn như tách chế độ xem đó thành hai chế độ xem và sau đó truy vấn họ hoặc bỏ qua chế độ xem hoàn toàn.
Aaron Bertrand

Tôi nghĩ rằng tôi đang cố gắng để đạt được những gì bạn đang đề xuất, nhưng tôi không hoàn toàn nắm bắt những gì tôi cần làm. Tôi nghĩ rằng chế độ xem di sản mà tôi đã quản lý để lập chỉ mục và cụ thể hóa thành một hỗ trợ ban nhạc dường như là một cách giải quyết khá tốt đối với giới hạn truy vấn phụ, và mặc dù nó hoạt động ít nhiều trong trạng thái hiện tại, nó rất dễ bị bổ sung phạm vi leo. Tôi đang vật lộn với ý tưởng thiết lập một quy trình để đưa vào một bảng cơ sở hoàn toàn mới sau khi quá trình nhập xảy ra và thay đổi khung nhìn để tham chiếu đến đó.
Avarkx

Câu trả lời:


4

Viết lại NOT EXISTSDISTINCTtham gia bất bình đẳng cho phép quan điểm được lập chỉ mục, nhưng có những lý do chính đáng mà điều này không được thực hiện phổ biến.

Kế hoạch thực hiện được tạo để xây dựng chỉ mục trên khung nhìn là không thể tránh khỏi khủng khiếp. Bất đẳng thức buộc một phép nối vật lý lồng nhau, ngoại trừ một giá trị, là một phép nối chéo. Việc thu gọn sản phẩm với một nhóm riêng biệt hoặc tương đương sẽ tạo ra kết quả chính xác, giả sử cột tham gia không thể rỗng (như trong mã ví dụ), nhưng nó sẽ không bao giờ hiệu quả. Sự không hiệu quả này sẽ chỉ phát triển tồi tệ hơn khi thời gian trôi qua và các bảng liên quan trở nên lớn hơn.

Các vấn đề tương tự ảnh hưởng đến kế hoạch thực hiện cho bất kỳ câu lệnh DML nào ảnh hưởng đến một bảng được tham chiếu bởi khung nhìn (bởi vì khung nhìn phải được đồng bộ hóa với các bảng cơ sở mọi lúc trong SQL Server). Nhìn vào kế hoạch thực hiện được tạo để thêm hoặc sửa đổi một hàng trong một trong hai bảng để xem ý tôi là gì.

Ở mức cao, vấn đề bạn đang đấu tranh là trình tối ưu hóa truy vấn SQL Server không phải lúc nào cũng tạo ra các kế hoạch tốt qua các chế độ xem bao gồm a UNION ALL. Nhiều tối ưu hóa mà chúng ta đã được cấp (như MAX-> TOP (1)) đơn giản là không được thực hiện trên toàn liên minh.

Đối với mỗi vấn đề bạn giải quyết, bạn sẽ tìm thấy một trường hợp khác trong đó tối ưu hóa bình thường và dự kiến ​​không xảy ra, dẫn đến một kế hoạch thực hiện với hiệu suất tuyệt vọng. Giải pháp rõ ràng là tránh sử dụng liên minh trong quan điểm. Cách bạn thực hiện điều này trong trường hợp của bạn phụ thuộc vào chi tiết, mặc dù chi tiết trong câu hỏi, có lẽ chỉ bạn biết.

Nếu bạn có không gian, một giải pháp là duy trì completelegacycác bảng cơ sở riêng biệt (bao gồm cả logic không tồn tại). Điều này không dẫn đến sự trùng lặp dữ liệu và đi kèm với các vấn đề đồng bộ hóa, nhưng theo kinh nghiệm của tôi, những cách này dễ giải quyết mạnh mẽ hơn nhiều so với việc cố gắng có được các khung nhìn hợp nhất để tạo ra các kế hoạch thực hiện tốt cho một loạt các truy vấn trong mọi trường hợp (hoặc thậm chí là hầu hết).

SQL Server cung cấp một số tính năng để hỗ trợ đồng bộ hóa dữ liệu, vì tôi chắc chắn rằng bạn biết, bao gồm theo dõi thay đổi, thay đổi dữ liệu, kích hoạt ... vv. Các chi tiết cụ thể của việc thực hiện nằm ngoài diễn đàn này. Điểm quan trọng là trình bày trình tối ưu hóa với các bảng cơ sở, không kết hợp tất cả các khung nhìn.


Cảm ơn cả bạn và @AaronBertrand cho đầu vào của bạn. Những hiểu biết và đề xuất của bạn được đánh giá rất cao! Tôi có thể sẽ kết thúc việc di chuyển thủ công dữ liệu bảng cũ vào bảng mới để tôi có thể thay đổi chế độ xem vì không còn cần phải liên kết từ bảng cũ nữa. Về mặt lý thuyết, sau đó tôi có thể bỏ hoàn toàn bảng kế thừa. Sẽ có những thách thức khác với cách tiếp cận này, nhưng như bạn đã đề cập, có lẽ những thách thức đó sẽ dễ quản lý hơn về lâu dài vì những gì tôi đang làm rõ ràng sẽ không hoạt động tốt, bao giờ hết.
Avarkx
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.