Lỗi tràn hàng 8k khi cập nhật hàng có kích thước 5k


8

Tôi đang cố gắng cập nhật bảng mục tiêu có một hàng có kích thước 5k thành một hàng có kích thước 5k.

Vì nó là một hàng nên dễ dàng biết kích thước thực của hàng:

select *
from sys.dm_db_index_physical_stats(DB_ID('RODS_HSD_ES'), 
OBJECT_ID(N'TBL_BM_HSD_SUBJECT_AN_148_REPRO'), NULL, NULL, 'DETAILED')

Tái sản xuất

Bảng không bị thay đổi kể từ khi tạo. không thấy bất kỳ lý do tại sao nó nên thất bại. Ý tưởng?


2
Tương tự như câu hỏi cuối cùng của bạn . Lỗi này trong khi xây dựng một bàn làm việc cho một loại quá i.stack.imgur.com/wenSE.png , i.stack.imgur.com/MVyXf.png
Martin Smith

Câu trả lời:


9

Vấn đề liên quan đến thực tế là bạn đang cập nhật khóa phân cụm và bảng đích xảy ra có sơ đồ phân vùng 1 . Khi SQL Server được yêu cầu cập nhật bất kỳ thành phần nào của khóa phân cụm, nó phải thực hiện một UPDATEDELETE, hoặc một bản cập nhật lai trong đó một số hàng được cập nhật tại chỗ, còn một số thì không.

Nếu bạn xóa chỉ mục được nhóm khỏi bảng đích, bạn sẽ thấy bản cập nhật hoạt động.

Thông báo lỗi, trong khi có lẽ hơi sai lệch, là chính xác vì kích thước hàng kết quả trong quá trình cập nhật vượt quá độ dài tối đa.

Tôi đề nghị bạn xem xét thay đổi cấu trúc của bảng thành:

  • không sử dụng VARCHAR(MAX)cho tất cả các cột. Nếu bạn không thực sự cần 2GB ký tự trong một cột, tại sao lại xác định cột theo cách đó? Xác định cột là kích thước tối đa sẽ gặp thực tế.
  • có lẽ chia bảng này thành nhiều bảng trong đó kích thước hàng tối đa kết quả nhỏ hơn 8060 byte. Có vẻ như bạn có một vài cụm logic của cột, chẳng hạn như V_MAX_xxx, V_64_xxxV_512_xxxcác cột vv

Để đơn giản hóa repro của bạn, bạn có thể muốn loại bỏ con trỏ và chỉ thực hiện thao tác DML sau:

UPDATE dbo.TBL_BM_HSD_SUBJECT_AN_148_REPRO_TARGET
SET [sampletime]  = '2015-12-29 01:11:26.687';

Cột trên là một trong các thành phần của khóa phân cụm và cũng là khóa phân vùng (cập nhật các cột khóa CI khác hoạt động tốt).

Với chỉ mục được nhóm tại chỗ, bạn gặp lỗi này:

Msg 511, Cấp 16, Bang 1, Dòng 1

Không thể tạo một hàng có kích thước 8287 lớn hơn kích thước hàng tối đa cho phép là 8060.

Các tuyên bố này đã bị chấm dứt.

Không có chỉ số cụm tại chỗ, tuyên bố thành công.


1 Điều thú vị là, nếu chúng ta loại bỏ các phân vùng từ repro, chúng tôi tìm thấy bản cập nhật thành công, ngay cả với các nhóm chỉ số tại chỗ.


1
Tôi nghĩ rằng chúng ta đang trên một con đường dẫn đến một giải pháp ở đây. Về cơ bản, sampletime là người duy nhất tôi phải thay đổi và đó là chỉ mục trong cụm chỉ vì bảng được phân vùng bởi nó. Vì vậy, một giải pháp sẽ là thay đổi cách phân vùng bảng (điều này gây đau đớn, nhưng có thể), và sau đó là chỉ mục được nhóm
Yosi Dahari

10

Bản cập nhật không thành công vì những lý do tương tự như những lý do tôi đã giải thích trong câu trả lời cho câu hỏi trước đó của bạn .

Trong trường hợp này, vì bạn có khả năng cập nhật nhiều hàng trong đó một cột khóa của một chỉ mục duy nhất được thay đổi * , SQL Server xây dựng một kế hoạch bao gồm các toán tử Tách, Sắp xếp và Thu gọn để tránh vi phạm khóa duy nhất trung gian (xem bài viết này để biết chi tiết) .

Do đó, toán tử Sắp xếp đã giới thiệu gặp một hàng trung gian (bao gồm cả các tổng phí bên trong) có chiều rộng vượt quá giới hạn, do đó, một lỗi được đưa ra. Thêm một OPTION (ROBUST PLAN)gợi ý cho truy vấn cập nhật cho thấy điều này là không thể tránh khỏi:

Msg 8619, Cấp 16, Trạng thái 2, Dòng 681
Bộ xử lý truy vấn không thể tạo kế hoạch truy vấn vì cần có bàn làm việc và kích thước hàng tối thiểu của nó vượt quá mức tối đa cho phép là 8060 byte. Một lý do điển hình tại sao một bàn làm việc được yêu cầu là mệnh đề GROUP BY hoặc ORDER BY trong truy vấn. Gửi lại truy vấn của bạn mà không có gợi ý ROBUST PLAN.

Các mối quan hệ dữ liệu nguồn / đích không rõ ràng với tôi từ một cái nhìn ngắn gọn, nhưng nếu bạn có thể đảm bảo rằng mỗi hoạt động cập nhật sẽ ảnh hưởng đến nhiều nhất một hàng, bạn có thể tránh sự cần thiết của Chia / Sắp xếp / Thu gọn bằng cách thêm TOP (1)vào câu lệnh cập nhật:

UPDATE TOP (1) [TBL_BM_HSD_SUBJECT_AN_148_REPRO_TARGET] 
SET ...

Đây là một chút của một hack, mặc dù. Lý tưởng nhất là việc xây dựng câu lệnh cập nhật và các chỉ mục sẽ cung cấp đủ thông tin cho trình tối ưu hóa để có thể thấy rằng nhiều nhất một hàng sẽ được cập nhật. Cụ thể, cách tốt nhất là viết các báo cáo cập nhật mang tính quyết định .

Với thiết kế kỳ quặc và thiếu rõ ràng trong câu hỏi, tôi thậm chí sẽ không cố gắng giải mã các mối quan hệ dữ liệu, hoặc thay đổi truy vấn & chỉ mục cần thiết để đạt được điều này một cách chi tiết.

* Như Martin Smith đã chỉ ra trong một bình luận, đây sẽ không phải là vấn đề trong tình huống cụ thể này nếu bảng không được phân vùng. Trong đó bản cập nhật đặt khóa thành cùng một giá trị xác định trong mỗi hàng, thì không cần phải phân tách / Sắp xếp / Thu gọn, trừ khi bảng cũng được phân vùng trên khóa đó. Vì vậy, một giải pháp thay thế cho truy vấn này là không phân vùng bảng vào thời gian .

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.