Vấn đề chính tăng dần - Cột hàng đầu mang nhãn hiệu Văn phòng phẩm - Máy chủ SQL


8

Tôi đã nghiên cứu các truy vấn chạy chậm trong cơ sở dữ liệu của chúng tôi và đã kết luận rằng đây là một vấn đề chính tăng dần cổ điển. Vì các hàng mới được chèn gần như liên tục và một đoạn SQL nhất định để lấy dữ liệu mới nhất ra khỏi DB chạy cứ sau 30 phút, tùy chọn đầu tiên cập nhật số liệu thống kê cứ sau 30 phút nghe có vẻ lãng phí tài nguyên.

Vì vậy, tôi đã xem xét Trace Flag 2389 về nguyên tắc sẽ giúp ích, tuy nhiên, điều đó đòi hỏi cột Hàng đầu phải được gắn nhãn là Tăng dần và khi tôi sử dụng Trace Flag 2388 để kiểm tra các chỉ số (PK), tôi thấy rằng cột hàng đầu thực sự là được gắn nhãn là Stationary - vì nó dành cho một số chỉ mục PK trên các bảng khác được cập nhật cùng một lúc.

nhập mô tả hình ảnh ở đây

Dường như không có nhiều hướng dẫn về kết quả trong việc xây dựng thương hiệu Văn phòng phẩm, tuy nhiên tôi đã tìm thấy KB2952101 nói rằng nếu ít hơn 90% số lần chèn lớn hơn giá trị tối đa cũ, thì nó sẽ được phân loại là Văn phòng phẩm. Tất cả các phần chèn của chúng tôi là các bài nộp mới và cột hàng đầu là cột IDENTITY lớn, vì vậy 100% các phần chèn phải lớn hơn giá trị tối đa trước đó.

Vì vậy, câu hỏi của tôi là tại sao cột sẽ được gắn nhãn là Văn phòng phẩm, khi nó rõ ràng là tăng dần?

Một nỗ lực trước đó để giải quyết vấn đề này đối với một số SQL đang chạy hàng ngày (hoạt động rất tốt) đã dẫn đến một công việc đang được thiết lập để cập nhật số liệu thống kê cho bảng này hàng đêm. Bản cập nhật không thực hiện FULLSCAN, vì vậy đôi khi có thể quét được lấy mẫu bị thiếu các hàng mới, vì vậy không phải lúc nào nó cũng hiển thị tăng dần?

Điều khác duy nhất tôi có thể nghĩ về điều đó có thể ảnh hưởng đến điều này, là chúng tôi có một công việc lưu trữ chạy phía sau hậu trường xóa các hàng trong một độ tuổi nhất định. Điều này có thể có ảnh hưởng đến việc xây dựng thương hiệu?

Máy chủ là SQL Server 2012 SP1.

Cập nhật : Một ngày khác, cập nhật số liệu thống kê khác - cùng nhãn hiệu văn phòng phẩm. Đã có 28049 chèn mới kể từ khi cập nhật số liệu thống kê trước đó. Mỗi hàng có dấu thời gian khi nó được chèn, vì vậy nếu tôi chọn max (id) từ bảng trong đó dấu thời gian <'20161102' Tôi nhận được 23313455 Tương tự, nếu tôi làm điều đó khi cập nhật ngày hôm nay, tôi sẽ nhận được 23341504.

Sự khác biệt giữa chúng là 28049 chèn mới, như bạn có thể thấy, tất cả các chèn mới đều được cung cấp các khóa tăng dần mới (như mong đợi), cho thấy cột hàng đầu nên được gắn nhãn tăng dần thay vì đứng yên.

Trong cùng thời gian, công việc lưu trữ của chúng tôi đã xóa 213.629 hàng (chúng tôi đang dần xóa dữ liệu cũ). Có bất kỳ cơ hội nào mà một số lượng giảm có thể đóng góp cho thương hiệu văn phòng phẩm không? Tôi đã thử nghiệm điều này trước đây và có vẻ như nó không tạo ra sự khác biệt nào.

Cập nhật 2 : Một ngày khác, cập nhật số liệu thống kê khác và cột hiện được gắn cờ là Tăng dần! Theo lý thuyết về việc xóa ảnh hưởng đến điều này, tôi đã kiểm tra tỷ lệ phần trăm cập nhật được chèn so với xóa, và ngày hôm qua 13% là phần chèn, trong khi hai ngày trước đó phần chèn chiếm khoảng 12%. Tôi không nghĩ rằng điều đó mang lại cho chúng tôi bất cứ điều gì kết luận.

Thật thú vị, một bảng liên quan có trung bình 4 hàng được chèn cho mỗi hàng được chèn vào bảng chính này và có các số liệu thống kê được cập nhật cùng lúc, có phải cột PK IDENTITY vẫn là Văn phòng phẩm không!?

Cập nhật 3 : Cuối tuần, chúng tôi nhận được nhiều chèn hơn. Sáng nay, cột hàng đầu đã trở lại Văn phòng phẩm. Trong bản cập nhật thống kê mới nhất, chúng tôi đã có 46840 lần chèn và chỉ có 34776 lần xóa.

Một lần nữa, thật thú vị, bảng liên quan mà tôi đã đề cập ở trên có cột hàng đầu được gắn nhãn là Tăng dần. Không có tài liệu có thể giải thích điều này?

Cập nhật 4 : Bây giờ đã được một tuần, công việc lưu trữ đã xóa phần tồn đọng, vì vậy chúng tôi liên tục xóa khoảng hai phần ba số lượng hàng được chèn. Các số liệu thống kê đang hiển thị kết quả khác nhau trên các bảng có liên quan, với một bảng hiển thị đứng yên và hai bảng hiển thị tăng dần, mặc dù tất cả chúng đều được cập nhật tương ứng.


Trong trường hợp của chúng tôi, tất cả các phần chèn đều có các giá trị vượt quá giá trị cao nhất trong biểu đồ, do đó, cột không được mang nhãn hiệu Văn phòng phẩm, vì vậy tôi đã không thử cờ. Đó là một lời giải thích tại sao SQL Server dường như tạo thương hiệu ngẫu nhiên cho các cột mà tôi thực sự theo đuổi. Cảm ơn.
Nik

Câu trả lời:


3

Dường như không có nhiều hướng dẫn về kết quả trong việc xây dựng thương hiệu Văn phòng phẩm, tuy nhiên tôi đã tìm thấy KB2952101 nói rằng nếu ít hơn 90% số lần chèn lớn hơn giá trị tối đa cũ, thì nó sẽ được phân loại là Văn phòng phẩm. Tất cả các phần chèn của chúng tôi là các bài nộp mới và cột hàng đầu là cột IDENTITY lớn, vì vậy 100% các phần chèn phải lớn hơn giá trị tối đa trước đó.

Vì vậy, câu hỏi của tôi là tại sao cột sẽ được gắn nhãn là Văn phòng phẩm, khi nó rõ ràng là tăng dần?

Nó sẽ có nhãn hiệu cố định nếu, như bạn đã nêu, rằng 10% hoặc nhiều hơn các phần chèn không tăng dần. Nếu 100% các phần chèn của bạn đúng như bạn nói ... thì bạn có thể không gặp vấn đề này, cho đến khi tất nhiên bạn xóa nhưng sau đó nó sẽ trở lại không xác định.

Đây là một lời trách móc về vấn đề của bạn:

use master;
go
-- create a database for this to test
create database AscendingKey;
go

use AscendingKey;
go
-- create a test table
create table dbo.AscendingKeyTableTest
(
    SomeData        char(100) default('A'),
    AscendingKey    bigint not null,
);
go

-- insert some dummy data
set nocount on
go

declare @i int = 1

while(@i <= 1000)
begin
    insert into AscendingKeyTableTest(AscendingKey) VALUES (@i);
    set @i += 1
end
go

-- create stats on the ascendingkey column
create statistics AscendingKeyStats on dbo.AscendingKeyTableTest(AscendingKey);
go

-- look at the stats
dbcc traceon(2388);
dbcc show_statistics('dbo.ascendingkeytabletest', ascendingkeystats);
dbcc traceoff(2388);
-- unknown

-- now insert a few more ascending
declare @i int;
declare @j int = 1;

SELECT @i = max(ascendingkey) from dbo.AscendingKeyTableTest;

while(@j <= 10)
begin
    insert into AscendingKeyTableTest(AscendingKey) VALUES (@i+@j);
    set @j += 1
end
go

-- check again
dbcc traceon(2388);
dbcc show_statistics('dbo.ascendingkeytabletest', ascendingkeystats);
dbcc traceoff(2388);
-- unknown

-- update the stats
update statistics ascendingkeytabletest(ascendingkeystats) with fullscan;

-- now insert a few more ascending
declare @i int;
declare @j int = 1;

SELECT @i = max(ascendingkey) from dbo.AscendingKeyTableTest;

while(@j <= 10)
begin
    insert into AscendingKeyTableTest(AscendingKey) VALUES (@i+@j);
    set @j += 1
end
go

-- update the stats
update statistics ascendingkeytabletest(ascendingkeystats) with fullscan;

-- check again
dbcc traceon(2388);
dbcc show_statistics('dbo.ascendingkeytabletest', ascendingkeystats);
dbcc traceoff(2388);

-- now insert a few more ascending
declare @i int;
declare @j int = 1;

SELECT @i = max(ascendingkey) from dbo.AscendingKeyTableTest;

while(@j <= 10)
begin
    insert into AscendingKeyTableTest(AscendingKey) VALUES (@i+@j);
    set @j += 1
end
go

-- update the stats
update statistics ascendingkeytabletest(ascendingkeystats) with fullscan;

-- check again
dbcc traceon(2388);
dbcc show_statistics('dbo.ascendingkeytabletest', ascendingkeystats);
dbcc traceoff(2388);
-- ascending!
-- we hit the 3x stats updates to have it 'learn'

-- what happens if we insert more than 10% that isn't ascending
declare @i int = 1;

while(@i <= 10)
begin
    insert into AscendingKeyTableTest(AscendingKey) VALUES (@i);
    set @i += 1
end
go

-- still says ascending... but...
dbcc traceon(2388);
dbcc show_statistics('dbo.ascendingkeytabletest', ascendingkeystats);
dbcc traceoff(2388);
go
-- what if we update again?
update statistics ascendingkeytabletest(ascendingkeystats) with fullscan;
go
-- stationary
dbcc traceon(2388);
dbcc show_statistics('dbo.ascendingkeytabletest', ascendingkeystats);
dbcc traceoff(2388);
go
-- get it back to ascending
declare @i int;

SELECT @i = max(ascendingkey) from dbo.AscendingKeyTableTest;

insert into AscendingKeyTableTest(AscendingKey) VALUES (@i+1);
update statistics ascendingkeytabletest(ascendingkeystats) with fullscan;

insert into AscendingKeyTableTest(AscendingKey) VALUES (@i+2);
update statistics ascendingkeytabletest(ascendingkeystats) with fullscan;

insert into AscendingKeyTableTest(AscendingKey) VALUES (@i+3);
update statistics ascendingkeytabletest(ascendingkeystats) with fullscan;
go

dbcc traceon(2388);
dbcc show_statistics('dbo.ascendingkeytabletest', ascendingkeystats);
dbcc traceoff(2388);
go

-- what about the deletes?
delete from AscendingKeyTableTest where AscendingKey % 3 = 0
go

update statistics ascendingkeytabletest(ascendingkeystats) with fullscan;
go

dbcc traceon(2388);
dbcc show_statistics('dbo.ascendingkeytabletest', ascendingkeystats);
dbcc traceoff(2388);
go
-- back to unknown

-- cleanup
use master
go

drop database AscendingKey
go

Tôi đã thực hiện một thử nghiệm nhanh bằng cách sử dụng cùng một kịch bản như trên nhưng chỉ chạy các phần chèn và xóa. Có vẻ như nếu bạn xóa một số lượng hàng lớn hơn nhiều so với chèn, nó sẽ trở lại trạng thái đứng yên (khoảng 10%). Trong dữ liệu cập nhật của bạn, bạn đã chèn khoảng 10% tất cả các thay đổi dữ liệu được thực hiện - có vẻ như việc xóa đang mang lại cho bạn sự đau buồn. Tại thời điểm này, tôi sẽ đề nghị cho phép các đối tượng thống kê tăng dần và sau đó đóng băng nó bằng cách không cập nhật nó.
Sean Gallardy

Tôi đã thử tạo lại những gì bạn đã làm và cuối cùng thêm 10 hàng nữa và xóa 1000, cập nhật số liệu thống kê, sau đó hiển thị số liệu thống kê và nó vẫn hiển thị tăng dần: Chèn kể từ lần cập nhật trước: 10, Xóa kể từ lần cập nhật cuối: 1000, Loại cột hàng đầu : Tăng dần. Không chắc chắn tại sao tôi nhận được một kết quả khác với bạn? Nếu kết quả của bạn là chính xác, đó có thể chỉ là một trường hợp đưa ra kết quả thấp hơn mức tối ưu bây giờ, sau đó khi hồ sơ lưu trữ của chúng tôi đã được xóa, hãy thử lại.
Nik

0

Theo ước tính của tôi, trừ khi bạn đang tạo cột khóa hàng đầu trên chính máy chủ, bạn có thể vào các ổ gà nhỏ dựa vào nó được tạo trên các máy khách riêng lẻ.

Ngoài ra, bạn đã thử Trace Flag 2371.

TF 2371 được ghi lại ở đây .

KB có tiêu đề "Kiểm soát hành vi tự động (AUTO_UPDATE_STATISTICS) trong SQL Server." và KB là 2754171.

Sẽ rất hữu ích nếu bạn liệt kê cho chúng tôi những tác động thực sự của dữ liệu mới không đưa nó vào thống kê kịp thời.

Đã chọn sai chỉ số. Và, nếu vậy bạn có thể vui lòng liệt kê cho chúng tôi các chỉ mục và khóa chính của chúng không?

Ngoài ra, bạn có thể vui lòng chia sẻ các gói được tạo khi thống kê được ghi ngày khi chúng kịp thời. Tôi sẽ muốn so sánh hai.

Tôi nghĩ rằng các quyết định Tối ưu hóa dựa trên chi phí (Quy tắc và Chi phí) của SQL là khá tốt; bên ngoài các khu vực bí truyền như thế này.

Nếu đây là trường hợp đặc biệt, giải thích thêm có thể hữu ích và biện minh cho việc mở Mục kết nối.

Bên cạnh đó, theo ý kiến ​​khiêm tốn của tôi, bạn sẽ có lợi ích tổng thể lớn hơn trong việc nhà cung cấp sử dụng SP so với SQL ad-hoc.


Cảm ơn, tất cả các ID đều được tạo bởi SQL Server. Tôi hiểu cờ 2371 chỉ làm cho các cập nhật thống kê thường xuyên hơn. Đánh giá theo bảng tại brentozar.com/archive/2016/03/ Mạnh , kích thước bảng của chúng tôi (14M hàng) và số lần chèn hàng ngày (28K hàng), số liệu thống kê sẽ vẫn chỉ được cập nhật sau mỗi 4 ngày hoặc lâu hơn, vì vậy trích xuất dữ liệu mới hầu hết thời gian sẽ không biết về dữ liệu mới. Các truy vấn tôi đã xem xét không phải là mối quan tâm, nó hiểu cách SQL Server tạo thương hiệu cho cột hàng đầu mà tôi muốn biết. Cảm ơn một lần nữa.
Nik
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.