Saya mencoba untuk memperbarui tabel target yang memiliki satu baris ukuran 5k ke satu baris ukuran 5k juga.
Karena satu baris mudah untuk mengetahui ukuran aktual baris:
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')
Tabel tidak diubah sejak pembuatan. tidak melihat alasan mengapa itu harus gagal. Ide ide?
sql-server
sql-server-2012
update
Yosi Dahari
sumber
sumber
Jawaban:
Masalahnya terkait dengan fakta Anda memperbarui kunci pengelompokan, dan tabel tujuan kebetulan memiliki skema partisi 1 . Ketika SQL Server diminta untuk memperbarui komponen kunci pengelompokan, itu harus melakukan
UPDATE
danDELETE
, atau pembaruan hibrid di mana beberapa baris diperbarui di tempat, dan beberapa tidak.Jika Anda menghapus indeks berkerumun dari tabel tujuan, Anda akan melihat pembaruan berfungsi.
Pesan kesalahan, meskipun mungkin sedikit menyesatkan, akurat karena ukuran baris yang dihasilkan selama pembaruan melebihi panjang maksimum.
Saya sarankan Anda mempertimbangkan mengubah struktur tabel menjadi:
VARCHAR(MAX)
untuk semua kolom itu. Jika Anda sebenarnya tidak membutuhkan 2GB karakter dalam satu kolom, mengapa mendefinisikan kolom seperti itu? Tentukan kolom menjadi ukuran maksimum yang akan ditemui secara realistis.V_MAX_xxx
,V_64_xxx
, danV_512_xxx
kolom, dllUntuk menyederhanakan repro Anda, Anda mungkin ingin menghilangkan kursor, dan hanya melakukan operasi DML berikut:
Kolom di atas adalah salah satu komponen kunci clustering dan juga kunci partisi (memperbarui kolom kunci CI lainnya berfungsi dengan baik).
Dengan indeks berkerumun di tempat, Anda mendapatkan kesalahan ini:
Tanpa indeks berkerumun di tempat, pernyataan berhasil.
1 Menariknya, jika kita menghilangkan partisi dari repro, kita menemukan pembaruan berhasil, bahkan dengan indeks berkerumun di tempat.
sumber
Pembaruan gagal karena alasan yang hampir sama dengan yang saya jelaskan sebagai jawaban atas pertanyaan Anda sebelumnya .
Dalam hal ini, karena Anda berpotensi memperbarui beberapa baris di mana kolom kunci dari indeks yang unik adalah berubah * , SQL Server membangun rencana yang mencakup Split, Sort, dan operator Ciutkan untuk menghindari menengah pelanggaran kunci unik (lihat artikel ini untuk rincian) .
Operator Urut yang diperkenalkan kemudian menemukan baris perantara (termasuk overhead internal) dengan lebar yang melebihi batas, sehingga kesalahan muncul. Menambahkan
OPTION (ROBUST PLAN)
petunjuk ke permintaan pembaruan menunjukkan ini tidak dapat dihindari:Hubungan data sumber / target tidak jelas bagi saya dari pandangan singkat, tetapi jika Anda dapat menjamin bahwa setiap operasi pembaruan akan memengaruhi paling banyak satu baris, Anda dapat menghindari kebutuhan Split / Sortir / Perkecil dengan menambahkan
TOP (1)
pernyataan pembaruan:Ini sedikit peretasan. Idealnya, konstruksi dan indeks pernyataan pembaruan harus memberikan informasi yang cukup kepada pengoptimal sehingga dapat melihat bahwa paling banyak satu baris akan diperbarui. Secara khusus, ini adalah praktik terbaik untuk menulis pernyataan pembaruan yang bersifat deterministik .
Mengingat desain yang aneh dan kurangnya kejelasan dalam pertanyaan, saya bahkan tidak mencoba untuk menguraikan hubungan data, atau perubahan permintaan & indeks yang akan diperlukan untuk mencapai ini secara detail.
* Sebagaimana Martin Smith tunjukkan dalam komentar, ini tidak akan menjadi masalah dalam situasi khusus ini jika tabel tidak dipartisi. Di mana pembaruan menetapkan kunci ke nilai deterministik yang sama di setiap baris, Split / Sortir / Perkecil tidak diperlukan, kecuali tabel juga dipartisi pada kunci itu. Jadi, solusi alternatif untuk kueri ini adalah tidak mempartisi tabel pada sampletime .
sumber