Tôi có nên vô hiệu hóa số liệu thống kê cập nhật tự động của Wap trong kịch bản lưu trữ dữ liệu không?


12

Tôi có kho dữ liệu 200 GB trong SQL Server.

Tôi đã trải qua thời gian thực hiện rất chậm đối với một số truy vấn; ví dụ 12 giờ cho một deletetruy vấn đơn giản với một inner join.

Sau khi thực hiện một số nghiên cứu với các kế hoạch thực hiện, tôi đã cập nhật số liệu thống kê của 2 bảng liên quan đến truy vấn, sử dụng WITH FULLSCANtùy chọn.

Truy vấn bây giờ thực hiện trong chưa đầy một giây, vì vậy nó xuất hiện các số liệu thống kê không được cập nhật.

Tôi đang xem xét việc vô hiệu hóa auto update statisticscơ sở dữ liệu và chạy UPDATE STATISTICSthủ công sau khi kho dữ liệu được tải. Kho dữ liệu được tải tăng dần từ hệ thống ERP nguồn hàng ngày, vào ban đêm.

Tôi có đúng không khi cho rằng auto update statisticstrong một tình huống lưu trữ dữ liệu không thực sự hữu ích? Thay vào đó, nó có ý nghĩa hơn để cập nhật số liệu thống kê thủ công sau khi dữ liệu được tải?


Đây là một bài đọc rất hay về thống kê: Simple-talk.com/sql/performance/, chúng tôi cũng đang chạy một công việc hàng ngày bằng giải pháp của Ola ola.hallengren.com/, để cập nhật số liệu thống kê về db ​​1TB. Tôi sẽ không vô hiệu hóa tùy chọn thống kê cập nhật tự động.
Joy Walker

1
Nó phụ thuộc rất nhiều vào số lượng bản ghi trong (các) bảng của bạn và số lượng bạn thêm trong một lô. Trong bảng hàng 1b nơi bạn thêm 20 triệu hàng mỗi đêm, số liệu thống kê của bạn sẽ được cập nhật sau mỗi 10 ngày, điều này không tốt.
JNK

2
Chỉ cần FYI - có một cờ theo dõi (2371) để thay đổi ngưỡng cập nhật thống kê từ 20% cố định thành tỷ lệ phần trăm động. Xem thêm ở đây: blogs.msdn.com/b/saponsqlserver/archive/2011/09/07/...
DaniSQL

Liên kết rất nhiều thông tin, cảm ơn! @JNK: Vâng, đó là một DB lớn. Bảng phân tầng có 300m + hàng và tùy thuộc vào ngày chúng ta chèn một thứ gì đó trong khoảng từ 1m đến 10m mỗi ngày. Sẽ xem xét kỹ hơn các số liệu thống kê, vì nó đã được đề xuất bởi câu trả lời dưới đây.
sada

Câu trả lời:


11

Đây là một whitepaper khi auto_update thống kê xảy ra . Dưới đây là các điểm nổi bật cập nhật tự động vis-a-vis để thống kê:

  • Kích thước bảng đã đi từ 0 đến> 0 hàng (kiểm tra 1).
  • Số lượng hàng trong bảng khi số liệu thống kê được thu thập là 500 hoặc ít hơn và colmodctr của cột hàng đầu của đối tượng thống kê đã thay đổi hơn 500 kể từ đó (thử nghiệm 2).
  • Bảng có hơn 500 hàng khi số liệu thống kê được thu thập và colmodctr của cột hàng đầu của đối tượng thống kê đã thay đổi hơn 500 + 20% số lượng hàng trong bảng khi thu thập số liệu thống kê (kiểm tra 3) .

Vì vậy, @JNK đã đưa ra quan điểm trong một nhận xét rằng nếu bạn có 1 tỷ hàng trong một bảng, bạn cần phải có 20.000.5000 ghi vào cột đầu tiên trong thống kê để kích hoạt cập nhật.

Hãy lấy cấu trúc sau:

CREATE TABLE dbo.test_table (
    test_table_id INTEGER IDENTITY(1,1) NOT NULL, 
    test_table_value VARCHAR(50), 
    test_table_value2 BIGINT, 
    test_table_value3 NUMERIC(10,2)
);

CREATE CLUSTERED INDEX cix_test_table ON dbo.test_table (test_table_id, test_table_value);

Bây giờ chúng ta có thể kiểm tra để xem những gì đã xảy ra trong đất thống kê.

select * 
    from sys.stats
        where object_id = OBJECT_ID('dbo.test_table')

stat_container

Tuy nhiên, để xem đây có phải là một đối tượng thống kê có ý nghĩa hay không, chúng ta cần phải:

dbcc show_statistics('dbo.test_table',cix_test_table)

biểu đồ

Vì vậy, thống kê này đã không được cập nhật. Đó là bởi vì có vẻ như số liệu thống kê không được cập nhật cho đến khi SELECTxảy ra và thậm chí sau đó SELECTphải vượt ra ngoài những gì SQL Server có trong biểu đồ của nó. Đây là một kịch bản thử nghiệm mà tôi đã chạy để kiểm tra điều này:

    CREATE TABLE test_table (
        test_table_id INTEGER IDENTITY(1,1) NOT NULL, 
        test_table_value VARCHAR(50), 
        test_table_value2 BIGINT, 
        test_table_value3 NUMERIC(10,2)
    );

    CREATE CLUSTERED INDEX cix_test_table ON test_table (test_table_id, test_table_value);

    ALTER TABLE test_table ADD CONSTRAINT pk_test_table PRIMARY KEY  (test_table_id)

    SELECT * 
        FROM sys.stats
            WHERE object_id = OBJECT_ID('dbo.test_table')

    --DBCC SHOW_STATISTICS('dbo.test_table',pk_test_table)
    DBCC SHOW_STATISTICS('dbo.test_table',cix_test_table) WITH STAT_HEADER;

declare @test int = 0

WHILE @test < 1
    BEGIN
        INSERT INTO test_table (test_table_value,test_table_value2,test_table_value3) VALUES
            ('stats test' + CAST(@test AS VARCHAR(10)),@test, @test)
        SET @test = @test + 1;
    END

SELECT 'one row|select < 1', * FROM test_table WHERE test_table_id < 1;
--DBCC SHOW_STATISTICS('dbo.test_table',pk_test_table);
DBCC SHOW_STATISTICS('dbo.test_table',cix_test_table) WITH STAT_HEADER;

SET @test = 1

WHILE @test < 500
    BEGIN
        INSERT INTO test_table (test_table_value,test_table_value2,test_table_value3) VALUES
            ('stats test' + CAST(@test AS VARCHAR(10)),@test, @test)
        SET @test = @test + 1;
    END

SELECT '100 rows(add 99)|select < 100',* FROM test_table WHERE test_table_id < 100;
--DBCC SHOW_STATISTICS('dbo.test_table',pk_test_table);
DBCC SHOW_STATISTICS('dbo.test_table',cix_test_table) WITH STAT_HEADER;
--get the table up to 500 rows/changes
WHILE @test < 500
    BEGIN
        INSERT INTO test_table (test_table_value,test_table_value2,test_table_value3) VALUES
            ('stats test' + CAST(@test AS VARCHAR(10)),@test, @test)
        SET @test = @test + 1;
    END
SELECT '500 rows(add 400)|select < 100',* FROM test_table WHERE test_table_id < 100;
DBCC SHOW_STATISTICS('dbo.test_table',cix_test_table) WITH STAT_HEADER;
SELECT '500 rows(add 400)|select < 500',* FROM test_table WHERE test_table_id < 500;
--DBCC SHOW_STATISTICS('dbo.test_table',pk_test_table);
DBCC SHOW_STATISTICS('dbo.test_table',cix_test_table) WITH STAT_HEADER;
--bump it to 501
SET @test = 500;
WHILE @test < 501
    BEGIN
        INSERT INTO test_table (test_table_value,test_table_value2,test_table_value3) VALUES
            ('stats test' + CAST(@test AS VARCHAR(10)),@test, @test)
        SET @test = @test + 1;
    END


SELECT '501 rows(add 1)|select < 501',* FROM test_table WHERE test_table_id < 501;
--DBCC SHOW_STATISTICS('dbo.test_table',pk_test_table);
DBCC SHOW_STATISTICS('dbo.test_table',cix_test_table) WITH STAT_HEADER;

--bump it to 600
SET @test = 501;
WHILE @test < 600
    BEGIN
        INSERT INTO test_table (test_table_value,test_table_value2,test_table_value3) VALUES
            ('stats test' + CAST(@test AS VARCHAR(10)),@test, @test)
        SET @test = @test + 1;
    END

SELECT '600 rows (add 100)|select < 600',* FROM test_table WHERE test_table_id < 600;
--DBCC SHOW_STATISTICS('dbo.test_table',pk_test_table);
DBCC SHOW_STATISTICS('dbo.test_table',cix_test_table) WITH STAT_HEADER;

--bump it to 700
SET @test = 600;
WHILE @test < 700
    BEGIN
        INSERT INTO test_table (test_table_value,test_table_value2,test_table_value3) VALUES
            ('stats test' + CAST(@test AS VARCHAR(10)),@test, @test)
        SET @test = @test + 1;
    END

SELECT '700 rows (add 100)|select < 700', * FROM test_table WHERE test_table_id < 700;
--DBCC SHOW_STATISTICS('dbo.test_table',pk_test_table);
DBCC SHOW_STATISTICS('dbo.test_table',cix_test_table) WITH STAT_HEADER;

--bump it to 1200
SET @test = 700;
WHILE @test < 1200
    BEGIN
        INSERT INTO test_table (test_table_value,test_table_value2,test_table_value3) VALUES
            ('stats test' + CAST(@test AS VARCHAR(10)),@test, @test)
        SET @test = @test + 1;
    END

SELECT '1200 rows (add 500)|select < 1200',* FROM test_table WHERE test_table_id < 1200;
--DBCC SHOW_STATISTICS('dbo.test_table',pk_test_table);
DBCC SHOW_STATISTICS('dbo.test_table',cix_test_table) WITH STAT_HEADER;
--DROP TABLE test_table

Thay vì mù quáng vô hiệu hóa số liệu thống kê auto_update, tôi sẽ thử kiểm tra tập dữ liệu của bạn xem có bị lệch không. Nếu dữ liệu của bạn thể hiện độ lệch đáng kể, thì bạn cần xem xét việc tạo số liệu thống kê được lọc và sau đó quyết định xem việc quản lý cập nhật thống kê theo cách thủ công có phải là hướng hành động chính xác hay không.

Để phân tích cho độ lệch, bạn cần chạy DBCC SHOW_STATISTICS(<stat_object>, <index_name>);(trong đoạn mã trên mà không có WITH STAT_HEADER) trên tổ hợp chỉ số / chỉ số cụ thể mà bạn muốn kiểm tra. Một cách nhanh chóng để nhãn cầu xiên của bạn sẽ là nhìn vào biểu đồ (tập kết quả thứ ba) và kiểm tra phương sai trong của bạn EQ_ROWS. Nếu nó khá nhất quán thì độ lệch của bạn là tối thiểu. Để đẩy nó lên, bạn nhìn vào RANGE_ROWScột và nhìn vào phương sai ở đó vì điều này đo lường có bao nhiêu hàng tồn tại giữa mỗi bước. Cuối cùng, bạn có thể lấy [All density]kết quả từ DENSITY_VECTOR(tập kết quả thứ hai) và nhân [Rows Sampled]giá trị đó với giá trị trong STAT_HEADER(tập kết quả đầu tiên) và xem kỳ vọng trung bình sẽ là bao nhiêu cho một truy vấn trên cột đó. Bạn so sánh mức trung bình đó vớiEQ_ROWS và nếu có nhiều nơi thay đổi đáng kể, thì bạn đã bị lệch.

Nếu bạn thấy rằng bạn có độ lệch, thì bạn cần xem xét việc tạo một số thống kê được lọc trên các phạm vi có mức rất cao RANGE_ROWSđể bạn có thể đưa ra các bước bổ sung để ước tính tốt hơn về các giá trị đó.

Khi bạn có các số liệu thống kê được lọc này, bạn có thể xem xét khả năng cập nhật thống kê theo cách thủ công.


Cảm ơn bạn đã trả lời toàn diện. Tôi không có nhiều kinh nghiệm với các số liệu thống kê và điều này dường như khó khăn hơn như tôi nghĩ. Chắc chắn sẽ xem xét kỹ hơn và làm theo hướng dẫn của bạn.
SASO
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.