Không loại bỏ phân vùng cho các giá trị cột phân vùng trong bảng tra cứu?


7

Tôi đã tạo một bảng được phân đoạn (như hiển thị bên dưới) và gieo 480 triệu hàng - khoảng 181 hàng cho mỗi tài khoản.

Tôi đang chạy các truy vấn cơ bản trước khi thêm chỉ mục. Tôi đã rất ngạc nhiên khi thấy rằng việc tìm kiếm ngày trên cột phân vùng không dẫn đến việc loại bỏ phân vùng ngay cả sau khi thêm option(recompile). Có phải đó là như thế nào với các bảng được phân vùng? Dường như với tôi giống cuộc sống thực hơn là mã hóa cứng các giá trị cột phân vùng của vị từ.

Cuối cùng, tôi sẽ thêm (các) chỉ mục và gửi lại ở đây nếu tôi có thắc mắc về điều đó. Tôi không muốn tiếp tục cho đến khi tôi cảm thấy thoải mái với câu trả lời trong bài viết này.

    --step 2 (after creating db)
    ALTER DATABASE partitionresearch
    ADD FILEGROUP January
    GO
    ALTER DATABASE partitionresearch
    ADD FILEGROUP February
    GO
    ALTER DATABASE partitionresearch
    ADD FILEGROUP March
    GO
    ALTER DATABASE partitionresearch
    ADD FILEGROUP April
    GO
    ALTER DATABASE partitionresearch
    ADD FILEGROUP May
    GO
    ALTER DATABASE partitionresearch
    ADD FILEGROUP June
    GO
    ALTER DATABASE partitionresearch
    ADD FILEGROUP July
    GO
    ALTER DATABASE partitionresearch
    ADD FILEGROUP August
    GO
    ALTER DATABASE partitionresearch
    ADD FILEGROUP September
    GO
    ALTER DATABASE partitionresearch
    ADD FILEGROUP October
    GO
    ALTER DATABASE partitionresearch
    ADD FILEGROUP November
    GO
    ALTER DATABASE partitionresearch
    ADD FILEGROUP December
    GO
    --step 3
    -- Table Partitioning in SQL Server
        ALTER DATABASE [Partitionresearch]
        ADD FILE 
        (
        NAME = [PartJan],
        FILENAME = 'C:\Program Files\Microsoft SQL Server\MSSQL14.mycompany2\MSSQL\DATA\PartJan.ndf',
            SIZE = 5080 KB, 
            MAXSIZE = UNLIMITED, 
            FILEGROWTH = 2040 KB
        ) TO FILEGROUP [January]

        ALTER DATABASE [Partitionresearch]
        ADD FILE 
        (
        NAME = [PartFeb],
        FILENAME = 'C:\Program Files\Microsoft SQL Server\MSSQL14.mycompany2\MSSQL\DATA\PartFeb.ndf',
            SIZE = 5080 KB, 
            MAXSIZE = UNLIMITED, 
            FILEGROWTH = 2040 KB
        ) TO FILEGROUP [February]

        ALTER DATABASE [Partitionresearch]
        ADD FILE 
        (
        NAME = [PartMar],
        FILENAME = 'C:\Program Files\Microsoft SQL Server\MSSQL14.mycompany2\MSSQL\DATA\PartMar.ndf',
            SIZE = 5080 KB, 
            MAXSIZE = UNLIMITED, 
            FILEGROWTH = 2040 KB
        ) TO FILEGROUP [March]

        ALTER DATABASE [Partitionresearch]
        ADD FILE 
        (
        NAME = [PartApr],
        FILENAME = 'C:\Program Files\Microsoft SQL Server\MSSQL14.mycompany2\MSSQL\DATA\PartApr.ndf',
            SIZE = 5080 KB, 
            MAXSIZE = UNLIMITED, 
            FILEGROWTH = 2040 KB
        ) TO FILEGROUP [April]

        ALTER DATABASE [Partitionresearch]
        ADD FILE 
        (
        NAME = [PartMay],
        FILENAME = 'C:\Program Files\Microsoft SQL Server\MSSQL14.mycompany2\MSSQL\DATA\PartMay.ndf',
            SIZE = 5080 KB, 
            MAXSIZE = UNLIMITED, 
            FILEGROWTH = 2040 KB
        ) TO FILEGROUP [May]

        ALTER DATABASE [Partitionresearch]
        ADD FILE 
        (
        NAME = [PartJun],
        FILENAME = 'C:\Program Files\Microsoft SQL Server\MSSQL14.mycompany2\MSSQL\DATA\PartJun.ndf',
            SIZE = 5080 KB, 
            MAXSIZE = UNLIMITED, 
            FILEGROWTH = 2040 KB
        ) TO FILEGROUP [June]

        ALTER DATABASE [Partitionresearch]
        ADD FILE 
        (
        NAME = [PartJul],
        FILENAME = 'C:\Program Files\Microsoft SQL Server\MSSQL14.mycompany2\MSSQL\DATA\PartJul.ndf',
            SIZE = 5080 KB, 
            MAXSIZE = UNLIMITED, 
            FILEGROWTH = 2040 KB
        ) TO FILEGROUP [July]

        ALTER DATABASE [Partitionresearch]
        ADD FILE 
        (
        NAME = [PartAug],
        FILENAME = 'C:\Program Files\Microsoft SQL Server\MSSQL14.mycompany2\MSSQL\DATA\PartAug.ndf',
            SIZE = 5080 KB, 
            MAXSIZE = UNLIMITED, 
            FILEGROWTH = 2040 KB
        ) TO FILEGROUP [August]

        ALTER DATABASE [Partitionresearch]
        ADD FILE 
        (
        NAME = [PartSep],
        FILENAME = 'C:\Program Files\Microsoft SQL Server\MSSQL14.mycompany2\MSSQL\DATA\PartSep.ndf',
            SIZE = 5080 KB, 
            MAXSIZE = UNLIMITED, 
            FILEGROWTH = 2040 KB
        ) TO FILEGROUP [September]

        ALTER DATABASE [Partitionresearch]
        ADD FILE 
        (
        NAME = [PartOct],
        FILENAME = 'C:\Program Files\Microsoft SQL Server\MSSQL14.mycompany2\MSSQL\DATA\PartOct.ndf',
            SIZE = 5080 KB, 
            MAXSIZE = UNLIMITED, 
            FILEGROWTH = 2040 KB
        ) TO FILEGROUP [October]

        ALTER DATABASE [Partitionresearch]
        ADD FILE 
        (
        NAME = [PartNov],
        FILENAME = 'C:\Program Files\Microsoft SQL Server\MSSQL14.mycompany2\MSSQL\DATA\PartNov.ndf',
            SIZE = 5080 KB, 
            MAXSIZE = UNLIMITED, 
            FILEGROWTH = 2040 KB
        ) TO FILEGROUP [November]

        ALTER DATABASE [Partitionresearch]
        ADD FILE 
        (
        NAME = [PartDec],
        FILENAME = 'C:\Program Files\Microsoft SQL Server\MSSQL14.mycompany2\MSSQL\DATA\PartDec.ndf',
            SIZE = 5080 KB, 
            MAXSIZE = UNLIMITED, 
            FILEGROWTH = 2040 KB
        ) TO FILEGROUP [December]

    --step 4
    -- Table Partitioning in SQL Server
    USE Partitionresearch
    GO

    CREATE PARTITION FUNCTION [MonthlyPartition] (date)
    AS RANGE RIGHT FOR VALUES ('20190201', '20190301', '20190401',
                   '20190501', '20190601', '20190701', '20190801', 
                   '20190901', '20191001', '20191101', '20191201');

    --step 5
    -- Table Partitioning in SQL Server
    USE Partitionresearch
    GO

    CREATE PARTITION SCHEME MonthWisePartition
    AS PARTITION MonthlyPartition
            TO (January, February, March, April, May, June, July, 
                August, September, October, November, December
                );
    --step 6
    create table dbo.partitionresearch 
    (
    tranid int identity(1,1),
    [Date] date,

    Account int,
    SeqNumber tinyint,
    AlertType int,
    IsFirst tinyint,
    Indicator1 int,
    [time] time
    )
    on monthwisepartition([date])

    --with partitioning help - 40 seconds (as opposed to 3 min 46 sec) , hovered over table scan and didnt see partition count, but clearly partitions (elimination) were used
    --did see scalar operators with values 5 and 10 which happens to be where these accounts are partition wise (may and october)
    use partitionresearch
    select * from dbo.partitionresearch --hoverd over and closest thing to partn help i saw were scalar operators 5 and 10
    where (date between '5/1/2019' and '5/31/2019' or date between '10/1/2019' and '10/31/2019') and
          account in (1000000,2000000) 
    ------------------------------------------------------------------------------------------------------------------------
    --with "partition help" from a lookup table--3 minutes 33 seconds
    use partitionresearch
    select a.* from dbo.partitionresearch a--hovered over and believe partns wont be used
    join [dbo].[monthlookup] b
    on a.date=b.date
    where account in (1000000,2000000) 
    ------------------------------------------------------------------------------------------------------------------------
--this is the date lookup table which isnt partitioned, thus not aligned
USE [partitionresearch]
GO

/****** Object:  Table [dbo].[monthlookup]    Script Date: 7/12/2019 6:24:35 PM ******/
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE TABLE [dbo].[monthlookup](
    [monthid] [int] IDENTITY(1,1) NOT NULL,
    [Date] [date] NOT NULL
) ON [PRIMARY]
GO

Câu trả lời:


7

Điều này không có sẵn trong sản phẩm cho hàng đống phân vùng. Nếu bạn thay đổi bảng để có một chỉ mục cửa hàng cột được phân vùng thì đôi khi bạn sẽ có thể loại bỏ các phân vùng thông qua việc loại bỏ nhóm hàng bằng bộ lọc bitmap, dường như đó là những gì bạn đang theo đuổi.

Tôi viết blog về điều này ở đây . Trích dẫn một phần nhỏ:

Chúng tôi biết rằng dựa trên dữ liệu trong bảng thứ nguyên mà SQL Server chỉ cần đọc hai phân vùng từ bảng thực tế. Trình tối ưu hóa truy vấn trong lý thuyết có thể làm tốt hơn nó không? Hãy xem xét thực tế rằng một bảng được phân vùng có tối đa 15000 phân vùng. Tất cả các giá trị phân vùng không thể trùng nhau và chúng không thay đổi nếu không có thao tác DDL. Khi xây dựng bảng băm, trình tối ưu hóa truy vấn có thể theo dõi phân vùng nào có ít nhất một hàng trong đó. Khi kết thúc quá trình xây dựng hàm băm, chúng ta sẽ biết chính xác phân vùng nào có thể chứa dữ liệu, do đó, các phân vùng còn lại có thể bị bỏ qua trong giai đoạn thăm dò.

Có lẽ điều này không được thực hiện bởi vì điều quan trọng đối với việc xây dựng hàm băm là độc lập với đầu dò. Có lẽ không có gì đảm bảo có sẵn vào đúng thời điểm mà toán tử bitmap sẽ được đẩy xuống toàn bộ quá trình quét trái ngược với toán tử luồng phân vùng. Có lẽ đây không phải là trường hợp phổ biến và việc tối ưu hóa không đáng để nỗ lực. Rốt cuộc, bạn có thường xuyên tham gia vào cột phân vùng thay vì lọc theo nó không?


2

Chỉ để hoàn thiện, bạn có thể loại bỏ phân vùng động , nhưng chỉ khi loại liên kết là các vòng lặp lồng nhau với các tham số tương quan.

Ví dụ: sử dụng chức năng và lược đồ phân vùng được cung cấp:

CREATE PARTITION FUNCTION MonthlyPartition ([date])
AS RANGE RIGHT FOR VALUES
(
    '20190201', '20190301', '20190401',
    '20190501', '20190601', '20190701', '20190801', 
    '20190901', '20191001', '20191101', '20191201'
);

CREATE PARTITION SCHEME MonthWisePartition
AS PARTITION MonthlyPartition ALL TO ([PRIMARY]);

và bảng:

CREATE TABLE dbo.PartitionResearch 
(
    tranid integer identity(1,1) NOT NULL,
    [Date] date NULL,
    Account integer NULL,
    SeqNumber tinyint NULL,
    AlertType integer NULL,
    IsFirst tinyint NULL,
    Indicator1 integer NULL,
    [time] time NULL
)
ON MonthWisePartition([Date]);

CREATE TABLE dbo.MonthLookup
(
    [MonthId] integer IDENTITY(1,1) NOT NULL,
    [Date] date NOT NULL
)
ON [PRIMARY];

Truy vấn không sử dụng loại bỏ phân vùng:

SELECT
    a.* 
FROM dbo.PartitionResearch AS a
JOIN dbo.MonthLookup AS b
    ON a.[Date]=b.[Date]
WHERE
    a.Account IN (1000000,2000000);

... tạo ra kế hoạch sau:

kế hoạch vòng lặp lồng nhau

Các thuộc tính của PartitionResearchquét bảng hiển thị loại bỏ phân vùng động bằng cách sử dụng ngày hiện tại từ MonthLookupbảng trên mỗi lần lặp của vòng lặp:

Loại bỏ phân vùng động

Tùy chọn đó được ưa thích ở đây vì các bảng trống. Trong trường hợp của bạn, trình tối ưu hóa ưa thích một kế hoạch tham gia băm vì lý do chi phí ước tính. Đưa ra một MonthLookupbảng có 56 hàng (như thể hiện trong kế hoạch của bạn), thay thế các vòng lặp lồng nhau sẽ quét một phân vùng duy nhất 56 lần. Trình tối ưu hóa (có thể đúng) đánh giá rằng sẽ tốt hơn nếu quét tất cả 12 phân vùng một lần thay thế.

Nếu bạn muốn kiểm tra dữ liệu của mình bằng cách loại bỏ phân vùng động, bạn có thể nhận được một kế hoạch như vậy với một OPTION (LOOP JOIN)gợi ý truy vấn. Chỉ với hai phân vùng được truy cập bởi truy vấn mẫu, ít nhất có thể hợp lý rằng hai phân vùng có thể được quét 28 lần mỗi phân vùng trong thời gian hợp lý.

Để có một chiến lược chung mạnh mẽ hơn, bạn sẽ cần phải viết T-SQL cụ thể để đạt được loại bỏ phân vùng, ví dụ như sử dụng $PARTITIONhàm, bảng tạm thời hoặc SQL động.


1

Sau khi hiểu rõ hơn về hướng được đưa ra bởi cộng đồng này, tôi đã cố gắng thử một nguyên mẫu trong đó SQL được tạo động dựa trên những gì bảng tra cứu chứa (tức là không tham gia). Có thể sau khi thay đổi cột phân vùng thành một cột mới chỉ gồm năm và tháng.

Tôi muốn dựa trên SQL động trên 1-12 biến khi cần với tùy chọn biên dịch lại. Thay vào đó (xem mã bên dưới) và để tiết kiệm thời gian, tôi chỉ đơn giản chứng minh rằng trong lý thuyết, SQL động có thể được sử dụng để khắc phục mọi giới hạn (trong lý do) liên quan đến bảng tra cứu và loại bỏ phân vùng.

Tôi đã xây dựng 2 chuỗi. Một với 2 bộ khai báo biến phạm vi ngày ( @low1,@high1,@low2,@high2). Một với một lựa chọn và vị ngữ tham chiếu các biến phạm vi ngày và hai tài khoản đích. Tôi đã thực hiện nối hai chuỗi và loại bỏ phân vùng tự tin đã được sử dụng. Việc chọn có một tùy chọn (biên dịch lại) ở cuối. Bộ nhớ cache đã bị xóa trước khi so sánh thời gian chạy từ thử nghiệm này sang thử nghiệm tiếp theo ... táo với táo. Một phần để chắc chắn rằng việc loại bỏ phân vùng thực sự xảy ra.

declare @sql1 varchar(500)=
'declare @low1 date ='+'''' +'5/1/19'+'''' +
'declare @low2 date ='+'''' +'10/1/19'+'''' +
'declare @high1 date ='+''''+'5/31/19' +'''' +
'declare @high2 date ='+''''+'10/31/19'+'''' 
declare @sql2 varchar(500)=
'select * from dbo.partitionresearch 
where (date between @low1 and @high1 or date between @low2 and @high2) and
      account in (1000000,2000000) 
OPTION (RECOMPILE)'
CHECKPOINT 
DBCC DROPCLEANBUFFERS
exec (@sql1+@sql2)
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.