Cách hợp lý để dự đoán hiệu suất truy vấn theo thời gian


7

Tôi có cơ sở dữ liệu SQL Server 2012 mà tôi đang sử dụng để lưu dữ liệu từ các tệp được xử lý. Chúng tôi đọc dữ liệu từ một thư mục, xử lý nó với python và lưu kết quả vào cơ sở dữ liệu.

Một trong những điều đầu tiên chúng tôi làm trong quy trình ETL của mình là kiểm tra xem tệp đã được xử lý chưa. Chúng tôi chỉ đơn giản là làm một:

SELECT id FROM table1 WHERE basename = <basename>

Nếu có kết quả, chúng tôi bỏ qua tệp, nếu không có kết quả, chúng tôi sẽ xử lý tệp. Ngay bây giờ truy vấn này mất ~ 250ms với ~ 5m hồ sơ. Chúng tôi đã có một chỉ mục không bao gồm trên basenamecột rồi.

Chúng tôi sẽ thấy khoảng 100-200k hồ sơ được thêm vào mỗi tháng. Chúng tôi nhận được các tập tin theo lô. Vì vậy, chúng tôi có thể thấy các tệp 2k và sau đó 2 giờ các tệp 2k khác. Một số ngày chúng tôi sẽ nhận được các tệp 10k, những ngày khác chúng tôi chỉ có thể nhận được các tệp 4k.

Giữ tất cả các biến khác giống nhau là có một quy tắc để chiếu khi chúng ta có thể gặp phải các vấn đề về hiệu năng (các truy vấn mất nhiều hơn 1 giây) với truy vấn này ngoài việc chèn 15-20 triệu bản ghi vào bảng và xem điều gì xảy ra?

Bảng DDL:

CREATE TABLE [dbo].[raw_records](
[id] [int] IDENTITY(1,1) NOT NULL,
[basename] [varchar](512) NULL,
[filename] [varchar](1024) NULL,
[file_size] [int] NULL,
[machine] [varchar](10) NULL,
[insert_timestamp] [datetime] NULL,
[raw_xml] [xml] NULL,
[process_status] [varchar](2048) NULL,

PRIMARY KEY CLUSTERED 
(
    [id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]

Mục lục:

CREATE NONCLUSTERED INDEX [basename_index] ON [dbo].[raw_records]
(
    [basename] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO

Bảng này được tạo ra từ lâu trước khi tôi bắt đầu làm việc với nó, vì vậy tôi giả sử ai đó chỉ tạo ra filenamechiều dài tối đa 1024 để giữ "đủ". Chắc chắn có thể thay đổi.

Các tệp được tạo ra có dấu thời gian và thông tin duy nhất trong chính tên tệp (ví dụ system1_metadata_timestamp.xml) một "hệ thống" không thể tạo (hoặc không bao giờ) tạo ra một tệp có cùng dấu thời gian.

select max(len(basename)), max(len(filename)) from dbo.raw_records;

trả về: basename- 143, filename- 168. Có lẽ là một điều tốt để thay đổi xuống tối đa 260.

process_statuscó lẽ cũng không cần phải dài như vậy, nhưng tôi cảm thấy rằng điều đó là hợp lý để đoán, bởi vì cột ở đó để giữ các thông báo lỗi từ giai đoạn xử lý. Tôi đã chạy một truy vấn trên đó và có tối đa 600 ký tự. Chúng tôi thường không truy vấn trên cột đó mặc dù. Nó chỉ là thông tin nhiều hơn để gỡ lỗi.

Tôi đang trải qua các ứng dụng dọn dẹp những thứ như vậy. Ở một số nơi nhất định tôi không thể tránh khỏi nó nhưng ở những nơi khác không thể làm gì nhiều về điều đó một cách đáng tiếc (ví dụ: thực sự cần phải lấy cột XML để trích xuất dữ liệu từ nó). Câu hỏi này chỉ đơn giản xuất phát từ việc xem hiệu suất của truy vấn đang được đề cập và không muốn nó tránh xa tôi. Đây là điều đầu tiên được thực hiện cho mọi tệp vì vậy nếu nó không hoạt động, thì cũng không có gì khác.

Câu trả lời:


12

Với một chỉ số tốt hiện tại, thời gian để xác định một hàng phù hợp sẽ mở rộng theo tỷ lệ logarit, miễn là bạn có chỗ cho chỉ mục trong bộ nhớ.

Tôi sẽ tạo chỉ mục UNIQUEvì tên cơ sở phải là duy nhất nếu không quy trình làm việc của bạn không hợp lệ và nó làm cho chỉ mục hiệu quả hơn.

CREATE UNIQUE INDEX IX_raw_records_basename
ON dbo.raw_records (basename);

Kiểm tra kế hoạch thực hiện cho truy vấn để đảm bảo chỉ mục đang được sử dụng.

Hãy chắc chắn rằng bạn có đủ dung lượng bộ nhớ cho chỉ mục và giả sử đồng thời sẽ không phải là vấn đề lớn, bạn nên làm tốt cho một số lượng lớn các hàng.

Tôi sẽ xem xét lại độ dài của các cột basenamefilenamevì trình tối ưu hóa truy vấn sẽ sử dụng độ dài khi tính toán lượng bộ nhớ cần phân bổ để chạy truy vấn. Ví dụ, nếu basenamecột sẽ không bao giờ chứa hơn 20 ký tự, nhưng bạn đã xác định nó là 512 ký tự, thì cấp bộ nhớ cho SELECT basename FROM dbo.raw_records;sẽ lớn hơn 25,6 lần so với yêu cầu thực tế. Độ dài cột thực sự quan trọng hơn nhiều so với hầu hết mọi người nhận ra.

Bạn cũng có thể thay đổi truy vấn SELECT 1 FROM table1 WHERE basename = <basename>theo cách mà bạn thậm chí sẽ không cần idvì tất cả những gì bạn đang cố gắng là xác minh sự tồn tại của nó. Chỉ làm những gì bạn thực sự cần. Có vẻ như chỉ số bạn hiển thị trong câu hỏi của bạn sẽ hoạt động tốt cho điều đó.


1
Tôi đã có một cảm giác tốt rằng người làm việc về điều này ban đầu đã tìm thấy điều này. stackoverflow.com/questions/4377740/ Mạnh
Kevin Vasko

Tôi không chắc chắn quy trình làm việc không hợp lệ nếu mỗi tệp dẫn đến nhiều hàng miễn là toàn bộ tệp được tải trong một giao dịch (vì vậy toàn bộ tệp có thể tải hoặc thất bại).
jpmc26

Ngoài ra, nếu không gian là một vấn đề bạn có thể muốn xem xét nén dữ liệu của chỉ mục và / hoặc bảng cơ sở. Điều này sẽ cho phép chỉ mục phù hợp với dung lượng bộ nhớ nhỏ hơn. Bạn sẽ cần kiểm tra xem nén ROW hay PAGE có tốt hơn hay không
Steve

0

Đối xử như nó là những gì nó là ... Một bảng dàn dựng. Đặt các tệp dữ liệu ở đó đủ lâu để hoàn thành quy trình ETL và sau đó cắt bớt bảng Chỉ cần giữ tên và ngày của tệp trong bảng "FileProcessLog" để bạn có thể duy trì bản ghi về các tệp đã được xử lý, khi chúng được xử lý và Mất bao lâu để hoàn thành. Giữ các tệp thô thực sự trong cơ sở dữ liệu của bạn lâu dài sẽ không có gì đáng tiếc ... Bạn có thực sự muốn bao gồm hàng terabyte tệp được lưu trữ trong tất cả các bản sao lưu hàng đêm của bạn không?


Đừng muốn cắt bớt cái bàn. Có, tôi có thể lưu trữ một tham chiếu đến các tệp, nhưng các tệp này có kích thước trung bình chỉ ~ 3KB để lưu trữ trên hệ thống tệp không cung cấp một lợi thế đáng kể (như hình ảnh hoặc dữ liệu nhị phân khác). Phần lớn trong số họ chỉ là 1-2KB. Dữ liệu XML được xử lý và lưu trữ vào một bảng được xử lý. Bảng này lưu trữ tất cả dữ liệu chúng tôi có để xử lý lại khi cần vì có những lúc mọi người muốn điều chỉnh cách chúng tôi muốn dịch dữ liệu. Chúng tôi cũng chỉ nói chuyện 10-15GB dữ liệu cho một năm dữ liệu.
Kevin Vasko

Tôi luôn cảm thấy hơi khó chịu khi thấy XML và các loại dữ liệu VARCHAR, NVARCHAR & BINary lớn, bởi vì tiềm năng luôn ở đó để có một lượng lớn dữ liệu được nhồi nhét vào chúng (2 hợp đồng cho XML và bất kỳ loại dữ liệu "MAX" nào) ... Điều đó nói rằng, 10 - 15 hợp đồng biểu diễn mỗi năm vẫn không có gì để hắt hơi. Nếu tôi có một sự lựa chọn trong vấn đề này, tôi muốn giữ các tệp không hoạt động trên một máy chủ tệp, hơn là giữ chúng trong cơ sở dữ liệu của tôi. Tôi sẽ lưu giữ hồ sơ về vị trí của chúng, trong cơ sở dữ liệu, trong trường hợp tôi cần chúng sau này, nhưng tôi không muốn đưa chúng vào khối lượng công việc bảo trì DB theo lịch trình của mình ...
Jason A. Long

-4

Làm thế nào để bạn nhận được param mà bạn đang truy vấn. Sẽ hiệu quả hơn nếu bạn có thể thực hiện các truy vấn của mình dựa trên các cột int không phải là varchar. Ngoài ra nếu bạn chỉ quan tâm đến sự tồn tại của một hàng như vậy trong bảng của bạn, bạn có thể thay đổi truy vấn của mình thành

SELECT 1 FROM table1 WHERE id = <id>

Trong trường hợp này, bạn không cần bao gồm nhiều cột hơn trong chỉ mục, vì vậy nó sẽ sử dụng ít bộ nhớ hơn và sẽ hoạt động tốt hơn.


1
Làm thế nào OP biết idsố trước? Họ cần phải tìm kiếm điều đó trong bảng bằng cách nào đó.
Max Vernon

Điểm chính của câu trả lời nếu có thể. Nhưng ngay cả khi không phải họ chỉ có thể chọn 1 thay vì chọn id và bao gồm id trong chỉ mục.
Artash Khachatryan

Tôi có thể làm điều SELECT 1đó sẽ là một cách tối ưu hóa hơn nữa. Đây basenamelà những gì sẽ có trong WHERE...mệnh đề và sẽ được lấy từ một bộ theo dõi thư mục (Tôi nhận được một sự kiện của một tập tin được sao chép vào thư mục tôi đang xem).
Kevin Vasko

5
SELECT 1,, SELECT idnó không quan trọng khi (id)chỉ số được nhóm. Cái idnày được bao gồm trong bất kỳ chỉ mục không cụm nào.
ypercubeᵀᴹ
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.