Hiệu suất của Bảng trong bộ nhớ kém hơn bảng dựa trên đĩa


10

Tôi có một bảng trong SQL Server 2014 giống như sau:

CREATE TABLE dbo.MyTable
(
[id1] [bigint] NOT NULL,
[id2] [bigint] NOT NULL,
[col1] [int] NOT NULL default(0),
[col2] [int] NOT NULL default(0)
)

với (id1, id2) là PK. Về cơ bản, id1 là một định danh để nhóm một tập hợp kết quả (id2, col1, col2), với pk là id2.

Tôi đang cố gắng sử dụng bảng trong bộ nhớ để loại bỏ bảng dựa trên đĩa hiện có vốn là nút cổ chai của tôi.

  • Dữ liệu trong bảng được ghi -> đọc -> xóa một lần.
  • Mỗi giá trị id1 có vài (hàng chục / hàng trăm) hàng nghìn id2.
  • Dữ liệu được lưu trữ trong bảng trong một khoảng thời gian rất ngắn, ví dụ 20 giây.

Các truy vấn được thực hiện trên bảng này như sau:

-- INSERT (can vary from 10s to 10,000s of records):
INSERT INTO MyTable
  SELECT @fixedValue, id2, col1, col2 FROM AnotherTable

-- READ:
SELECT id2, col1
FROM MyTable INNER JOIN OtherTbl ON MyTable.id2 = OtherTbl.pk
WHERE id1 = @value
ORDER BY col1

-- DELETE:
DELETE FROM MyTable WHERE id1 = @value

Đây là định nghĩa hiện tại mà tôi đã sử dụng cho bảng:

CREATE TABLE dbo.SearchItems
(
  [id1] [bigint] NOT NULL,
  [id2] [bigint] NOT NULL,
  [col1] [int] NOT NULL default(0),
  [col2] [int] NOT NULL default(0)

  CONSTRAINT PK_Mem PRIMARY KEY NONCLUSTERED (id1,id2),
  INDEX idx_Mem HASH (id1,id2) WITH (BUCKET_COUNT = 131072)
) WITH (MEMORY_OPTIMIZED = ON, DURABILITY = SCHEMA_ONLY)

Thật không may, định nghĩa này dẫn đến sự suy giảm hiệu năng liên quan đến tình huống trước đó với một bảng dựa trên đĩa. Thứ tự cường độ cao hơn hoặc thấp hơn 10% (trong một số trường hợp đạt 100%, do đó gấp đôi thời gian).

Trên hết, tôi đã mong đợi sẽ đạt được một siêu lợi thế trong các kịch bản có tính đồng thời cao, với kiến ​​trúc không khóa được quảng cáo bởi Microsoft. Thay vào đó, các màn trình diễn tệ nhất chính xác là khi có một số người dùng đồng thời chạy một số truy vấn trên bàn.

Câu hỏi:

  • BucksET_COUNT chính xác để đặt là gì?
  • Tôi nên sử dụng loại chỉ số nào?
  • Tại sao hiệu suất kém hơn so với bảng dựa trên đĩa?

Một truy vấn của sys.dm_db_xtp_hash_index_stats trả về:

tổng_bucket_count = 131072
blank_bucket_count = 0
avg_chain_len = 873
max_chain_length = 1009

Tôi đã thay đổi số lượng xô để đầu ra từ sys.dm_db_xtp_hash_index_stats là:

tổng_bucket_count = 134217728
blank_bucket_count = 131664087
avg_chain_len = 1
max_chain_length = 3

Tuy nhiên, kết quả gần như giống nhau, nếu không nói là tồi tệ hơn.


Bạn có chắc là bạn không chạy vào đánh hơi thông số? Bạn đã thử chạy các truy vấn với OPTION(OPTIMIZE FOR UNKNOWN)(xem Gợi ý Bảng ) chưa?
TT.

Tôi đoán là bạn đang gặp vấn đề về chuỗi hàng. Bạn có thể cho chúng tôi đầu ra của select * from sys.dm_db_xtp_hash_index_stats ? Ngoài ra, liên kết này sẽ trả lời hầu hết / tất cả các câu hỏi của bạn: msdn.microsoft.com/en-us/l
Library / 50

4
Chỉ số băm chỉ hữu ích cho các vị từ trên cả hai cột được bao gồm. Bạn đã thử mà không có một chỉ số băm trên bàn?
Mikael Eriksson

Tôi đã thấy rằng những cải tiến hiệu suất tốt nhất với công nghệ trong bộ nhớ chỉ có thể đạt được bằng cách sử dụng các quy trình lưu trữ được biên dịch tự nhiên .
Daniel Hutmacher

@DanielHutmacher FWIW Tôi đã thấy các ví dụ ngược lại trong đó tất cả lợi ích là từ việc loại bỏ chốt và thêm các thủ tục được biên dịch hữu ích đã cải thiện không hoặc không đáng kể. Tôi không nghĩ có bất kỳ chỗ nào cho một tuyên bố chăn (mặc dù bạn có thể đúng trong trường hợp này, tôi thậm chí không nhìn vào chi tiết).
Aaron Bertrand

Câu trả lời:


7

Mặc dù bài đăng này sẽ không phải là một câu trả lời đầy đủ do thiếu thông tin, nhưng nó sẽ có thể chỉ cho bạn đi đúng hướng hoặc có được cái nhìn sâu sắc mà sau này bạn có thể chia sẻ với cộng đồng.

Thật không may, định nghĩa này dẫn đến sự suy giảm hiệu năng liên quan đến tình huống trước đó với một bảng dựa trên đĩa. Thứ tự cường độ cao hơn hoặc thấp hơn 10% (trong một số trường hợp đạt 100%, do đó gấp đôi thời gian).

Trên hết, tôi đã mong đợi sẽ đạt được một siêu lợi thế trong các kịch bản có tính đồng thời cao, với kiến ​​trúc không khóa được quảng cáo bởi Microsoft. Thay vào đó, các màn trình diễn tệ nhất chính xác là khi có một số người dùng đồng thời chạy một số truy vấn trên bàn.

Điều này là rắc rối vì nó chắc chắn không phải là trường hợp. Một số khối lượng công việc nhất định không dành cho các bảng bộ nhớ (SQL 2014) và một số khối lượng công việc tự cho vay. Trong hầu hết các tình huống có thể có một cú va chạm tối thiểu trong hiệu suất chỉ bằng cách di chuyển và chọn các chỉ mục thích hợp.

Ban đầu tôi đã suy nghĩ rất hẹp về các câu hỏi của bạn về vấn đề này:

Câu hỏi:

  • BucksET_COUNT chính xác để đặt là gì?
  • Tôi nên sử dụng loại chỉ số nào?
  • Tại sao hiệu suất kém hơn so với bảng dựa trên đĩa?

Ban đầu tôi tin rằng có một vấn đề với thực tế trong bảng bộ nhớ và các chỉ mục không được tối ưu. Mặc dù có một số vấn đề với định nghĩa chỉ số băm được tối ưu hóa bộ nhớ, tôi tin rằng vấn đề thực sự xảy ra với các truy vấn được sử dụng.

-- INSERT (can vary from 10s to 10,000s of records):
INSERT INTO MyTable
  SELECT @fixedValue, id2, col1, col2 FROM AnotherTable

Việc chèn này phải cực kỳ nhanh nếu nó chỉ liên quan đến bảng nhớ. Tuy nhiên, nó cũng liên quan đến một bảng dựa trên đĩa và chịu tất cả các khóa và chặn liên quan đến điều đó. Vì vậy, lãng phí thời gian thực ở đây là trên bảng dựa trên đĩa.

Khi tôi thực hiện một thử nghiệm nhanh với 100.000 hàng chèn từ bảng dựa trên đĩa sau khi tải dữ liệu vào bộ nhớ - đó là thời gian phản hồi dưới giây. Tuy nhiên, hầu hết dữ liệu của bạn chỉ được lưu giữ trong một khoảng thời gian rất ngắn, dưới 20 giây. Điều này không cho nó nhiều thời gian để thực sự sống trong bộ nhớ cache. Ngoài ra, tôi không chắc AnotherTablethực sự lớn đến mức nào và không biết các giá trị có được đọc ra khỏi đĩa hay không. Chúng tôi phải dựa vào bạn cho những câu trả lời.

Với truy vấn Chọn:

SELECT id2, col1
FROM MyTable INNER JOIN OtherTbl ON MyTable.id2 = OtherTbl.pk
WHERE id1 = @value
ORDER BY col1

Một lần nữa, chúng tôi rất hài lòng về hiệu suất bảng dựa trên đĩa + đĩa. Ngoài ra, các loại không rẻ trên các chỉ mục HASH và nên sử dụng một chỉ mục không bao gồm. Điều này được gọi ra trong hướng dẫn Index tôi liên kết trong các ý kiến.

Để đưa ra một số sự kiện dựa trên nghiên cứu thực tế, tôi đã tải SearchItemsvào bảng bộ nhớ với 10 triệu hàng và AnotherTablevới 100.000 vì tôi không biết kích thước hoặc số liệu thống kê thực tế của nó. Sau đó tôi đã sử dụng truy vấn chọn ở trên để thực thi. Ngoài ra, tôi đã tạo một phiên sự kiện mở rộng trên Wait_completed và đặt nó vào bộ đệm vòng. Nó đã được làm sạch sau mỗi lần chạy. Tôi cũng đã chạy DBCC DROPCLEANBUFFERSđể mô phỏng một môi trường nơi tất cả dữ liệu có thể không phải là bộ nhớ cư trú.

Kết quả không có gì ngoạn mục khi nhìn chúng trong chân không. Vì máy tính xách tay mà tôi đang thử nghiệm này đang sử dụng ổ SSD cao cấp hơn, nên tôi đã giảm hiệu năng dựa trên đĩa một cách giả tạo cho VM tôi đang sử dụng.

Các kết quả được đưa ra mà không có thông tin chờ đợi sau 5 lần truy vấn trên bảng dựa trên bộ nhớ (loại bỏ tham gia và không có truy vấn phụ). Điều này là khá nhiều như mong đợi.

Tuy nhiên, khi sử dụng truy vấn ban đầu, tôi đã chờ đợi. Trong trường hợp này, đó là PAGEIOLATCH_SH, có nghĩa là dữ liệu đang được đọc trên đĩa. Vì tôi là người dùng duy nhất trong hệ thống này và không dành thời gian để tạo môi trường thử nghiệm lớn để chèn, cập nhật, xóa đối với bảng đã tham gia, tôi không mong đợi bất kỳ khóa hoặc chặn nào có hiệu lực.

Trong trường hợp này, một lần nữa, phần thời gian đáng kể được dành cho bảng dựa trên đĩa.

Cuối cùng là truy vấn xóa. Việc tìm các hàng dựa trên ID1 không thực sự hiệu quả với chỉ mục có. Mặc dù đúng là các biến vị ngữ bằng là chỉ số băm phù hợp với mục đích nào, nhóm mà dữ liệu rơi vào được dựa trên toàn bộ các cột được băm. Do đó id1, id2 trong đó id1 = 1, id2 = 2 và id1 = 1, id2 = 3 sẽ băm vào các nhóm khác nhau vì hàm băm sẽ nằm ngang (1,2) và (1,3). Đây sẽ không phải là một phạm vi quét B-Tree đơn giản vì các chỉ mục băm không được cấu trúc theo cùng một cách. Sau đó, tôi hy vọng đây không phải là chỉ số lý tưởng cho hoạt động này, tuy nhiên tôi sẽ không mong đợi nó sẽ nhận được các đơn đặt hàng có cường độ lâu hơn như kinh nghiệm. Tôi sẽ quan tâm đến việc xem Wait_info về điều này.

Trên hết, tôi đã mong đợi sẽ đạt được một siêu lợi thế trong các kịch bản có tính đồng thời cao, với kiến ​​trúc không khóa được quảng cáo bởi Microsoft. Thay vào đó, các màn trình diễn tệ nhất chính xác là khi có một số người dùng đồng thời chạy một số truy vấn trên bàn.

Mặc dù đúng là các khóa được sử dụng để thống nhất logic, các thao tác vẫn phải là nguyên tử. Điều này được thực hiện thông qua một toán tử so sánh dựa trên CPU đặc biệt (đó là lý do tại sao In-Memory chỉ hoạt động với một số [mặc dù gần như tất cả các cpus được thực hiện trong 4 năm qua]. Do đó, chúng tôi không nhận được mọi thứ miễn phí, vẫn sẽ có một thời gian để hoàn thành các hoạt động này.

Một điểm khác được đưa ra là trong hầu hết tất cả các truy vấn, giao diện được sử dụng là T-SQL (và không phải là các XUÂN được biên dịch tự nhiên) mà tất cả đều chạm vào ít nhất một bảng dựa trên đĩa. Đây là lý do tại sao tôi tin rằng, cuối cùng, chúng ta thực sự không có bất kỳ hiệu suất tăng nào vì chúng ta vẫn bị hạn chế về hiệu suất của các bảng dựa trên đĩa.

Theo sát:

  1. Tạo một phiên sự kiện mở rộng cho Wait_completed và chỉ định SPID mà bạn biết. Chạy truy vấn và cung cấp cho chúng tôi đầu ra hoặc tiêu thụ nội bộ.

  2. Cung cấp cho chúng tôi cập nhật về đầu ra từ # 1.

  3. Không có số ma thuật để xác định số lượng xô cho các chỉ số băm. Về cơ bản miễn là các thùng không đầy đủ và các chuỗi hàng ở dưới 3 hoặc 4, hiệu suất sẽ ở mức chấp nhận được. Điều này giống như hỏi, "Tôi nên đặt tệp nhật ký của mình thành gì?" - nó sẽ phụ thuộc vào mỗi quy trình, mỗi cơ sở dữ liệu, mỗi loại sử dụng.

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.