Hợp nhất tràn kích thước hàng trong SQL Server - Không thể tạo một hàng có kích thước ..


8

Bảng đích mà tôi đang cố gắng hợp nhất dữ liệu có ~ 660 cột. Mã cho hợp nhất:

MERGE TBL_BM_HSD_SUBJECT_AN_1 AS targetTable
USING
        (                
SELECT * 
FROM TBL_BM_HSD_SUBJECT_AN_1_STAGING
WHERE [ibi_bulk_id] in (20150520141627106) and  id in(101659113)
    ) AS sourceTable 
ON (...)
WHEN MATCHED AND ((targetTable.[sampletime] <= sourceTable.[sampletime]))
        THEN UPDATE SET ...
WHEN NOT MATCHED 
        THEN INSERT (...)
    VALUES (...)

Lần đầu tiên tôi chạy cái này (tức là khi bảng trống), nó đã dẫn đến thành công và chèn một hàng.

Lần thứ hai tôi chạy cái này, với cùng một bộ dữ liệu, một lỗi đã được trả về:
Không thể tạo một hàng có kích thước 8410 lớn hơn kích thước hàng tối đa cho phép là 8060.

Tại sao lần thứ hai tôi cố gắng hợp nhất cùng một hàng đã được chèn, nó lại dẫn đến một lỗi. Nếu hàng này vượt quá kích thước hàng tối đa, nó sẽ không thể chèn nó ở vị trí đầu tiên.

Vì vậy, tôi đã thử hai điều, (và đã thành công!):

  • Xóa phần "KHI KHÔNG ĐƯỢC MATCHED" khỏi câu lệnh hợp nhất
  • Chạy một câu lệnh cập nhật với cùng một hàng tôi đã cố gắng hợp nhất

Tại sao cập nhật bằng cách sử dụng hợp nhất không thành công, trong khi chèn thì và cập nhật trực tiếp cũng không?

CẬP NHẬT:

Được quản lý để tìm kích thước hàng thực tế - 4978. Tôi đã tạo một bảng mới chỉ có hàng này và tìm kích thước hàng theo cách này: nhập mô tả hình ảnh ở đây

Và tôi vẫn không thấy cái gì vượt quá giới hạn cho phép.

CẬP NHẬT (2):

Sinh sản đầy đủ

Đã thực hiện một nỗ lực rằng bản sao này sẽ không yêu cầu bất kỳ đối tượng phụ trợ bổ sung nào và dữ liệu sẽ bị (phần nào) bị xáo trộn.

Đã thử điều này trên một số máy chủ, từ phiên bản 2012 và một từ năm 2008, và có thể sao chép hoàn toàn trong tất cả chúng.

Câu trả lời:


10

Tại sao lần thứ hai tôi cố gắng hợp nhất cùng một hàng đã được chèn, nó lại dẫn đến một lỗi. Nếu hàng này vượt quá kích thước hàng tối đa, nó sẽ không thể chèn nó ở vị trí đầu tiên.

Đầu tiên, cảm ơn bạn cho kịch bản sinh sản.

Vấn đề không phải là SQL Server không thể chèn hoặc cập nhật một hàng người dùng cụ thể . Như bạn đã lưu ý, một hàng đã được chèn vào bảng chắc chắn không thể quá lớn về cơ bản để SQL Server xử lý.

Sự cố xảy ra do việc MERGEtriển khai SQL Server thêm thông tin được tính toán (dưới dạng các cột bổ sung) trong các bước trung gian trong kế hoạch thực hiện. Thông tin bổ sung này là cần thiết vì lý do kỹ thuật, để theo dõi xem mỗi hàng sẽ dẫn đến chèn, cập nhật hoặc xóa; và cũng liên quan đến cách SQL Server thường tránh các vi phạm khóa tạm thời trong quá trình thay đổi chỉ mục.

Công cụ lưu trữ máy chủ SQL yêu cầu các chỉ mục phải là duy nhất (bên trong, bao gồm mọi trình duy nhất ẩn) mọi lúc - vì mỗi hàng được xử lý - thay vì ở đầu và cuối của giao dịch hoàn chỉnh. Trong các MERGEtrường hợp phức tạp hơn , điều này đòi hỏi phải phân tách (chuyển đổi bản cập nhật thành xóa và chèn riêng), Sắp xếp và Thu gọn tùy chọn (biến các phần chèn và cập nhật liền kề trên cùng một khóa thành bản cập nhật). Thêm thông tin .

Bên cạnh đó, lưu ý rằng vấn đề không xảy ra nếu bảng mục tiêu là một đống (bỏ chỉ mục cụm để thấy điều này). Tôi không khuyến nghị đây là cách khắc phục, chỉ đề cập đến nó để làm nổi bật mối liên hệ giữa việc duy trì tính duy nhất của chỉ số mọi lúc (được nhóm trong trường hợp hiện tại) và Phân tách-Thu gọn.

Trong các truy vấn đơn giản MERGE , với các chỉ mục duy nhất phù hợp và mối quan hệ đơn giản giữa các hàng nguồn và đích (thường khớp với một ONmệnh đề có tất cả các cột chính), trình tối ưu hóa truy vấn có thể đơn giản hóa phần lớn logic chung, dẫn đến các kế hoạch tương đối đơn giản không yêu cầu Dự án phân tách-thu gọn hoặc thu hẹp phân đoạn để kiểm tra các hàng mục tiêu chỉ được chạm một lần.

Trong các MERGE truy vấn phức tạp , với logic mờ hơn, trình tối ưu hóa thường không thể áp dụng các đơn giản hóa này, cho thấy nhiều logic cơ bản phức tạp hơn cần thiết để xử lý chính xác (lỗi sản phẩm và có rất nhiều ).

Truy vấn của bạn chắc chắn đủ điều kiện là phức tạp. Các ONđiều khoản không phù hợp với các phím số (và tôi hiểu tại sao), và 'bảng nguồn' là một tự join liên quan đến một chức năng cửa sổ bảng xếp hạng (một lần nữa, với lý do):

MERGE MERGE_REPRO_TARGET AS targetTable
USING
(
    SELECT * FROM 
    (
        SELECT 
            *, 
            ROW_NUMBER() OVER (
                PARTITION BY ww,id, tenant 
                ORDER BY 
                (
                    SELECT COUNT(1) 
                    FROM MERGE_REPRO_SOURCE AS targetTable
                    WHERE 
                        targetTable.[ibi_bulk_id] = sourceTable.[ibi_bulk_id] 
                        AND targetTable.[ibi_row_id] <> sourceTable.[ibi_row_id] 
                        AND 
                        (
                            (targetTable.[ww] = sourceTable.[ww]) 
                            AND (targetTable.[id] = sourceTable.[id]) 
                            AND (targetTable.[tenant] = sourceTable.[tenant])
                        ) 
                        AND NOT ((targetTable.[sampletime] <= sourceTable.[sampletime]))
                ),
                sourceTable.ibi_row_id DESC
            ) AS idx
        FROM MERGE_REPRO_SOURCE sourceTable 
        WHERE [ibi_bulk_id] in (20150803110418887)
    ) AS bulkData
    where idx = 1
) AS sourceTable 
ON 
    (targetTable.[ww] = sourceTable.[ww]) 
    AND (targetTable.[id] = sourceTable.[id]) 
    AND (targetTable.[tenant] = sourceTable.[tenant])
...

Điều này dẫn đến nhiều cột được tính toán thêm, chủ yếu được liên kết với Tách và dữ liệu cần thiết khi một bản cập nhật được chuyển đổi thành cặp chèn / cập nhật. Các cột bổ sung này dẫn đến một hàng trung gian vượt quá 8060 byte được phép tại Sắp xếp trước đó - cột chỉ sau Bộ lọc:

Sắp xếp vấn đề

Lưu ý rằng Bộ lọc có 1.319 cột (biểu thức và cột cơ sở) trong Danh sách đầu ra. Đính kèm trình gỡ lỗi cho thấy ngăn xếp cuộc gọi tại điểm ngoại lệ nghiêm trọng được nêu ra:

Dấu vết ngăn xếp

Lưu ý khi thông qua rằng vấn đề không nằm ở Spool - ngoại lệ được chuyển thành cảnh báo về tiềm năng cho một hàng quá lớn.

Tại sao cập nhật bằng cách sử dụng hợp nhất không thành công, trong khi chèn thì và cập nhật trực tiếp cũng không?

Một bản cập nhật trực tiếp không có độ phức tạp bên trong giống như MERGE. Đây là một hoạt động đơn giản hơn về cơ bản có xu hướng đơn giản hóa và tối ưu hóa tốt hơn. Xóa NOT MATCHEDmệnh đề cũng có thể loại bỏ đủ độ phức tạp sao cho lỗi không được tạo ra trong một số trường hợp. Điều đó không xảy ra với repro, tuy nhiên.

Cuối cùng, lời khuyên của tôi là tránh MERGEnhững nhiệm vụ lớn hơn hoặc phức tạp hơn. Kinh nghiệm của tôi là các câu lệnh chèn / cập nhật / xóa riêng biệt có xu hướng tối ưu hóa tốt hơn, dễ hiểu hơn và cũng thường thực hiện tốt hơn về tổng thể, so với MERGE.

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.