Apa skenario penggunaan yang valid untuk tabel HEAP?

31

Saat ini saya sedang melakukan beberapa impor data ke sistem lama dan menemukan bahwa sistem ini tidak menggunakan indeks berkerumun tunggal. Pencarian Google cepat memperkenalkan saya pada konsep tabel HEAP dan sekarang saya ingin tahu dalam skenario penggunaan apa tabel HEAP harus lebih disukai daripada tabel berkerumun?

Sejauh yang saya mengerti tabel HEAP hanya akan berguna untuk tabel audit dan / atau di mana memasukkan lebih sering daripada memilih. Ini akan menghemat ruang disk dan I / O disk karena tidak ada indeks berkerumun untuk mempertahankan dan fragmentasi tambahan tidak akan menjadi masalah karena bacaan yang sangat langka.

marc.d
sumber
1
Apakah Anda berbicara tentang SQL Server?
a_horse_with_no_name
@a_horse_with_no_name ya, saya lupa menyebutkan sry itu
marc.d
Heap tables baik untuk tabel dengan jutaan baris yang sangat dikuasai oleh pengguna. The downside adalah bahwa mereka dapat mengambil banyak ruang karena data secara fisik disimpan tidak disortir. Selain itu, Anda mengandalkan indeks untuk disetel ke kueri Anda. Saya telah bekerja di tempat yang sama sekali tidak menggunakan indeks berkerumun karena masalah kinerja. Mungkin karena pilihan indeks berkerumun yang buruk tetapi jika Anda hanya menggunakan tabel tumpukan Anda tidak perlu khawatir tentang hal itu. Solusi yang lebih baik adalah dengan menggunakan edisi enterprise sql server dan mempartisi tabel secara horizontal. Tetapi jika Anda tidak memiliki hak
Lihat juga stackoverflow.com/questions/1341393/… .
Jon of All Trades

Jawaban:

22

Satu-satunya kegunaan yang valid adalah untuk

  • tabel staging yang digunakan dalam proses impor / ekspor / ETL.
  • ad-hoc, cadangan sementara dan pendek dari tabel menggunakan SELECT * INTO..

Staging tables biasanya cukup datar dan terpotong sebelum / sesudah digunakan.

Perhatikan bahwa indeks berkerumun biasanya sedikit kecil dibandingkan dengan ukuran data: data adalah tingkat terendah dari struktur indeks.

Heap tables juga memiliki masalah. Setidaknya ini:

Lihat juga

gbn
sumber
2
Biasanya menggunakan tumpukan untuk dua hal yang terpisah. ETL staging dan work tables yang saya gunakan untuk menyimpan sementara data saat set adalah besar agar temp table bekerja dengan efektif. Semuanya terpotong pada beban berikutnya.
Zane
Pertanyaan yang bagus.
Zane
1
Satu sedikit perubahan - jika Anda melakukan SELECT INTO untuk membuat cadangan cepat sebuah tabel kecil sebelum Anda melakukan perubahan, heap dibuat secara default. Saya akan mengatakan itu adalah penggunaan yang valid - tapi itu hanya nit-picking. Saya ingin menyingkirkan tumpukan itu segera setelah saya tahu pekerjaan saya selesai.
Brent Ozar
@ BrentOzar: Setuju, saya melakukannya sendiri setiap saat. Semangat jawaban saya adalah "tabel jangka panjang dan persisten" tapi saya akan memperbarui
gbn
9

Pertimbangan Utama

Saya melihat satu keuntungan penting untuk tumpukan dan satu untuk tabel berkerumun, ditambah pertimbangan ketiga yang bisa berjalan baik.

  • Tumpukan menghemat lapisan tipuan. Indeks berisi ID baris, menunjuk langsung (well, tidak benar-benar, tetapi selurus mungkin) ke lokasi disk. Dengan demikian, pencarian indeks terhadap tumpukan harus biaya sekitar setengah indeks pencarian non-cluster terhadap tabel berkerumun.

  • Indeks berkerumun diurutkan, per se, berkat indeks (hampir) gratis. Karena indeks pengelompokan tercermin dalam urutan fisik data, maka dibutuhkan ruang yang relatif sedikit di atas data aktual itu sendiri, yang tentu saja Anda harus tetap menyimpannya. Karena dipesan secara fisik, pemindaian rentang terhadap indeks ini dapat mencari ke titik awal dan kemudian zip bersama ke titik akhir dengan sangat efisien.

  • Indeks pada tumpukan referensi RID, yang 64 bit. Seperti disebutkan, indeks yang tidak berkerumun di tabel berkerumun merujuk kunci pengelompokan, yang bisa lebih kecil (32-bit INT), sama (64-bit BIGINT), atau lebih besar (48-bit DATETIME2()plus 32-bit INT, atau GUID 128-bit). Jelas referensi yang lebih luas membuat indeks lebih besar dan lebih mahal.

Persyaratan Ruang

Dengan dua tabel ini:

CREATE TABLE TmpClustered
(
ID1 INT NOT NULL,
ID2 INT NOT NULL
)
ALTER TABLE TmpClustered ADD CONSTRAINT PK_Tmp1 PRIMARY KEY CLUSTERED (ID1)
CREATE UNIQUE INDEX UQ_Tmp1 ON TmpClustered (ID2)

CREATE TABLE TmpNonClustered
(
ID1 INT NOT NULL,
ID2 INT NOT NULL
)
ALTER TABLE TmpNonClustered ADD CONSTRAINT PK_Tmp2 PRIMARY KEY NONCLUSTERED (ID1)
CREATE UNIQUE INDEX UQ_Tmp2 ON TmpNonClustered (ID2)

... masing-masing diisi dengan catatan 8,7 M, ruang yang dibutuhkan adalah 150 MB untuk data untuk keduanya; 120 MB untuk indeks tabel berkerumun, 310 MB untuk indeks tabel tidak berkerumun. Ini mencerminkan bahwa indeks cluster lebih sempit daripada RID, dan bahwa indeks clustering kebanyakan adalah "freebie." Tanpa indeks unik aktif ID2, ruang indeks yang dibutuhkan turun hingga 155 MB untuk tabel non-cluster (setengah, seperti yang Anda harapkan) tetapi hanya 150 KB untuk PK cluster - hampir tidak ada.

Jadi indeks non-clustered dari bidang 32-bit dalam tabel clustered dengan indeks 32-bit (total 64 bit, nominal) mengambil 120 MB, sedangkan indeks bidang 32-bit di heap dengan 64-bit RID (total 96 bit, nominal) mengambil 155 MB, sedikit kurang dari peningkatan 50% yang secara naif diharapkan akan beralih dari kunci 64-bit ke 96-bit, tetapi tentu saja ada overhead yang mengurangi perbedaan ukuran yang efektif.

Mengisi dua tabel dan membuat indeks mereka mengambil jumlah waktu yang sama untuk setiap tabel. Menjalankan tes sederhana yang melibatkan pemindaian atau pencarian, saya tidak menemukan perbedaan kinerja material di antara tabel, yang cocok dengan kertas putih Microsoft yang terkait dengan gbn. Makalah tersebut memang menunjukkan perbedaan yang signifikan untuk akses yang sangat bersamaan; Saya tidak yakin mengapa itu terjadi, semoga seseorang dengan pengalaman lebih banyak daripada saya dengan sistem OLTP volume tinggi dapat memberi tahu kami.

Menambahkan ~ 40 byte data panjang variabel acak tidak cukup mengubah kesetaraan ini. Mengganti INTs dengan UUID lebar juga tidak (masing-masing tabel diperlambat dengan tingkat yang sama). Jarak tempuh Anda mungkin bervariasi, tetapi dalam kebanyakan kasus apakah indeks tersedia lebih penting daripada jenis apa.

Potongan-potongan

Melakukan pemindaian rentang terhadap indeks yang tidak berkerumun - baik karena tabelnya adalah tumpukan atau indeks bukan indeks berkerumun - melibatkan pemindaian indeks dan kemudian melakukan pencarian terhadap tabel untuk setiap klik. Ini bisa sangat mahal, jadi kadang-kadang lebih murah hanya memindai tabel. Anda dapat mengatasinya dengan indeks penutup. Ini berlaku apakah Anda telah mengelompokkan meja Anda atau tidak.

Seperti yang ditunjukkan @gbn, tidak ada cara sederhana untuk memadatkan tumpukan. Namun, jika meja Anda meningkat secara bertahap seiring waktu - kasus yang sangat umum - akan ada sedikit pemborosan karena ruang yang dibebaskan oleh penghapusan akan diisi oleh data baru.

Beberapa diskusi tabel tumpukan vs berkerumun yang saya lihat membuat argumen strawman yang penasaran bahwa tumpukan tanpa indeks lebih rendah daripada tabel berkerumun karena selalu membutuhkan pemindaian tabel. Ini memang benar, tetapi perbandingan yang lebih bermakna adalah "tabel berkerumun besar yang diindeks dengan baik" vs. Jika meja Anda sangat kecil atau Anda selalu akan melakukan pemindaian tabel, maka tidak masalah jika Anda mengelompokkannya atau tidak.

Karena setiap indeks dalam tabel berkerumun referensi indeks pengelompokan, mereka berlaku semua indeks yang meliputi. Kueri yang mereferensikan kolom yang diindeks dan kolom pengelompokan dapat melakukan pemindaian indeks tanpa pencarian tabel. Ini umumnya tidak berharga jika indeks pengelompokan Anda adalah kunci sintetis, tetapi jika itu adalah kunci bisnis yang harus Anda ambil kembali, itu adalah fitur yang bagus.

TL; DR

Saya seorang pria data warehousing, bukan ahli OLTP. Untuk tabel fakta saya hampir selalu menggunakan indeks pengelompokan pada bidang yang sebagian besar kemungkinan membutuhkan pemindaian rentang, biasanya bidang tanggal. Untuk tabel dimensi, saya mengelompokkan pada PK sehingga didaftar untuk menggabungkan bergabung dengan tabel fakta.

Ada beberapa alasan untuk menggunakan indeks pengelompokan, tetapi jika tidak ada alasan yang berlaku maka overhead mungkin tidak bermanfaat. Saya menduga ada banyak "kami selalu melakukannya dengan cara ini" dan "itu hanya praktik terbaik" di belakang orang yang menggunakan indeks berkerumun secara universal. Cobalah kedua dengan Anda data dan Anda beban dan melihat apa yang terbaik.

Jon dari Semua Perdagangan
sumber
5

Saya pikir mengatakan "Satu-satunya penggunaan yang valid adalah untuk pementasan tabel yang digunakan dalam proses impor / ekspor / ETL" sedikit membatasi untuk sedikitnya. Anda harus mengambil kasus penggunaan yang diharapkan sistem tertentu dan kemudian memilih berdasarkan pada kelebihan tumpukan atau indeks tabel terorganisir (saya tahu, istilah Oracle tetapi menggambarkannya dengan baik).

Gudang kami memuat ~ 1,5 miliar baris sehari dan harus mendukung penulisan dan pemrosesan yang sangat bersamaan serta membaca. Toko relasional mendukung database OLAP dan dengan demikian bacaannya cenderung berupa pemindaian tabel. Laporan dan umpan hilir yang dihasilkan juga umumnya tidak cukup selektif sehingga indeks apa pun akan berguna. Sistem mendukung jendela geser data dan dengan demikian setelah sebuah tabel dimuat, kita jarang menulis lagi dan mengingat implementasi yang agak buruk dari partisi tabel yang membutuhkan kunci Sch-M untuk pemisahan partisi, sakelar dan penggabungan versus kunci Sch-S untuk dibaca dll , sistem harus menggunakan banyak tabel, meskipun kami memiliki beberapa tabel yang dipartisi juga. Penggunaan banyak tabel memfasilitasi kemudahan segmentasi data dan siklus pembersihan sementara juga mengurangi pertikaian.

Dengan demikian, tambahan overhead dari tabel indeks terorganisir (tabel berkerumun) pada beberapa kolom (s) sewenang-wenang dibandingkan dengan dapat bcp ke tumpukan, memproses partisi OLAP, melakukan beberapa permintaan pemindaian tabel dan kemudian 3 hari kemudian drop artinya itu tidak layak. Perhatikan bahwa dalam kasus kami, data kembali dari gugus kotak besar sehingga tidak ada urutan untuk data juga, jadi memasukkan ke dalam tabel dengan indeks berkerumun dapat memperkenalkan masalah lain seperti "hot spot" dan pemisahan halaman dan sejenisnya.

Juga, saya pikir argumen tentang halaman yang tersebar agak tidak jujur. Indeks yang dikelompokkan juga dapat membuat halaman mereka tersebar di seluruh file. Hanya saja setelah pengindeksan ulang (dengan asumsi lebih dari 1000 halaman) ini mungkin lebih baik daripada tumpukan tetapi kemudian Anda juga harus mengindeks ulang juga.

Dimungkinkan juga untuk menghemat ruang menggunakan kolom yang jarang dan kompresi jika itu menjadi masalah. Memang benar bahwa dalam beberapa kasus memilih di atas meja dengan indeks berkerumun bisa lebih cepat tetapi Anda harus menimbang bahwa dengan sumber daya yang diperlukan untuk memuat dan memeliharanya.

[Sunting] Saya mungkin harus menjelaskan bahwa hanya tabel fakta non-partisi kami yang banyak. Tabel yang dipartisi dan tabel dimensi semuanya memiliki indeks berkerumun untuk mendukung pencarian yang efisien, dll. [Sunting2] Dikoreksi 2,5 miliar hingga 1,5 miliar. Tut, kedua angka itu bersebelahan. Apa yang terjadi ketika mengetik tanggapan pada telepon saya kira ...

Phil Stephenson
sumber