sql primary key dan index


106

Katakanlah saya memiliki baris ID (int) dalam database yang ditetapkan sebagai kunci utama. Jika saya sering menanyakan ID, apakah saya juga perlu mengindeksnya? Atau apakah itu kunci utama berarti sudah diindeks?

Alasan saya bertanya adalah karena di MS SQL Server saya dapat membuat indeks pada ID ini, yang seperti yang saya nyatakan adalah kunci utama saya.

Sunting: pertanyaan tambahan - apakah ada salahnya untuk mengindeks tambahan kunci utama?

Jawaban:


73

Anda benar, ini membingungkan karena SQL Server memungkinkan Anda membuat indeks duplikat di bidang yang sama. Tetapi fakta bahwa Anda dapat membuat yang lain tidak menunjukkan bahwa indeks PK juga belum ada.

Indeks tambahan tidak ada gunanya, tetapi satu-satunya kerugian (sangat kecil) adalah ukuran file tambahan dan overhead pembuatan baris.


39
Kerusakan indeks yang tidak terpakai memang sangat merugikan. Untuk satu hal, indeks menghabiskan penyimpanan. Untuk hal lain, ini memperlambat penulisan dan pembaruan. Selalu hapus indeks yang tidak akan digunakan.
Pacerier

50

Seperti yang telah dikatakan orang lain, kunci primer diindeks secara otomatis.

Membuat lebih banyak indeks pada kolom kunci utama hanya masuk akal saat Anda perlu mengoptimalkan kueri yang menggunakan kunci utama dan beberapa kolom spesifik lainnya. Dengan membuat indeks lain pada kolom kunci utama dan menyertakan beberapa kolom lain dengannya, Anda dapat mencapai pengoptimalan yang diinginkan untuk sebuah kueri.

Misalnya Anda memiliki tabel dengan banyak kolom tetapi Anda hanya menanyakan kolom ID, Nama dan Alamat. Mengambil ID sebagai kunci utama, kita dapat membuat indeks berikut yang dibangun di atas ID tetapi menyertakan kolom Nama dan Alamat.

CREATE NONCLUSTERED INDEX MyIndex
ON MyTable(ID)
INCLUDE (Name, Address)

Jadi, saat Anda menggunakan kueri ini:

SELECT ID, Name, Address FROM MyTable WHERE ID > 1000

SQL Server akan memberi Anda hasil hanya menggunakan indeks yang Anda buat dan tidak akan membaca apa pun dari tabel sebenarnya.


28

CATATAN: Jawaban ini membahas pengembangan kelas perusahaan dalam skala besar .

Ini adalah masalah RDBMS, bukan hanya SQL Server, dan perilakunya bisa sangat menarik. Pertama, meskipun kunci primer secara otomatis (unik) diindeks, itu TIDAK mutlak. Ada kalanya kunci utama TIDAK diindeks secara unik.

Di sebagian besar RDBMS, indeks unik akan secara otomatis dibuat pada kunci utama jika belum ada . Oleh karena itu, Anda dapat membuat indeks Anda sendiri pada kolom kunci utama sebelum mendeklarasikannya sebagai kunci utama, kemudian indeks tersebut akan digunakan (jika dapat diterima) oleh mesin database saat Anda menerapkan deklarasi kunci utama. Seringkali, Anda dapat membuat kunci utama dan mengizinkan indeks unik defaultnya dibuat, lalu membuat indeks alternatif Anda sendiri di kolom itu, lalu melepaskan indeks default.

Sekarang untuk bagian yang menyenangkan - kapan Anda TIDAK menginginkan indeks kunci utama yang unik? Anda tidak menginginkannya, dan tidak dapat mentolerirnya, ketika tabel Anda memperoleh cukup data (baris) untuk membuat pemeliharaan indeks menjadi terlalu mahal. Ini bervariasi berdasarkan perangkat keras, mesin RDBMS, karakteristik tabel dan database, dan beban sistem. Namun, ini biasanya mulai terwujud setelah tabel mencapai beberapa juta baris.

Masalah penting adalah bahwa setiap penyisipan baris atau pembaruan kolom kunci utama menghasilkan pemindaian indeks untuk memastikan keunikan. Pemindaian indeks unik itu (atau ekuivalennya di RDBMS mana pun) menjadi jauh lebih mahal seiring pertumbuhan tabel, hingga mendominasi kinerja tabel.

Saya telah berkali-kali menangani masalah ini dengan tabel sebesar dua miliar baris, penyimpanan 8 TB, dan empat puluh juta baris sisipan per hari. Saya ditugaskan untuk mendesain ulang sistem yang terlibat, termasuk menjatuhkan indeks kunci primer unik secara praktis sebagai langkah pertama. Memang, menurunkan indeks itu perlu dalam produksi hanya untuk memulihkan dari pemadaman, bahkan sebelum kami mendekati desain ulang. Desain ulang itu termasuk menemukan cara lain untuk memastikan keunikan kunci utama dan menyediakan akses cepat ke data.


Bagaimana jika kuncinya adalah kunci autoincrement int atau bigint? Apakah SQL Server cukup pintar untuk tidak melakukan pemindaian indeks unik dalam kasus ini?
quillbreaker

1
@quillbreaker: IDENTITYbidang tidak dijamin unik. Bagaimanapun, pengguna dapat memasukkan nilai duplikat jika mereka pengguna IDENTITY_INSERT.

Saya tahu ini adalah topik kuno, tetapi saya tidak mengerti bagaimana pemindaian keunikan dari satu indeks akan membebani sistem. Pemindaian pohon B + harus O (log n) * v di mana v dibatasi overhead untuk fragmentasi indeks, keseimbangan pohon tidak sempurna, dll. Jadi, 2 miliar baris akan menjadi basis log 2 dari 2.000.000.000 (sekitar 31 pencarian) kali, katakanlah, 2 atau 3 atau bahkan 10. 40 juta sisipan per hari adalah sekitar 462 / detik, ~ 100 IO per sisipan ... Ahh ... Oh. Saya melihat. Dan ini sebelum SSD tersebar luas.
Charles Burns

Kecuali jika Anda menjatuhkan batasan keunikan, bukankah overhead untuk memeriksa keunikan setiap baris jauh lebih besar?
Max Candocia


9

Berikut bagian dari MSDN :

Saat Anda menentukan batasan PRIMARY KEY untuk tabel, Database Engine memberlakukan keunikan data dengan membuat indeks unik untuk kolom kunci utama. Indeks ini juga memungkinkan akses cepat ke data saat kunci utama digunakan dalam kueri. Oleh karena itu, kunci utama yang dipilih harus mengikuti aturan untuk membuat indeks unik.


8

PK akan menjadi indeks berkerumun kecuali Anda menentukan non berkerumun


3

Mendeklarasikan PRIMARY KEYatau UNIQUEkendala menyebabkan SQL Server secara otomatis membuat indeks.

Indeks unik dapat dibuat tanpa mencocokkan batasan, tetapi batasan (baik kunci utama atau unik) tidak dapat ada tanpa indeks unik.

Dari sini, pembuatan batasan akan:

  • menyebabkan indeks dengan nama yang sama dibuat
  • tolak menjatuhkan indeks yang dibuat karena batasan tidak diperbolehkan ada tanpanya

dan pada saat yang sama menghilangkan batasan akan menurunkan indeks terkait.

Jadi, apakah sebenarnya ada perbedaan antara a PRIMARY KEYatau UNIQUE INDEX:

  • NULLnilai tidak diperbolehkan masuk PRIMARY KEY, tapi diperbolehkan dalam UNIQUEindeks; dan seperti pada operator set (UNION, EXCEPT, INTERSECT), di sini NULL = NULLartinya Anda hanya dapat memiliki satu nilai karena dua NULLditemukan sebagai duplikat satu sama lain;
  • hanya satu yang PRIMARY KEYmungkin ada per tabel sementara 999 indeks unik dapat dibuat
  • ketika PRIMARY KEYbatasan dibuat, itu dibuat sebagai clustered kecuali sudah ada indeks berkerumun pada tabel atau NONCLUSTEREDdigunakan dalam definisinya; ketika UNIQUEindeks dibuat, itu dibuat seolah- NONCLUSTEREDolah tidak spesifik untuk menjadi CLUSTEREDdan yang sudah tidak ada;

2

Menjadikannya kunci utama juga secara otomatis membuat indeks untuknya.


1

Nah di SQL Server, umumnya kunci primer diindeks secara otomatis. Ini benar, tetapi tidak menjamin kueri yang lebih cepat. Kunci utama akan memberi Anda kinerja yang sangat baik bila hanya ada 1 bidang sebagai kunci utama. Namun, jika ada beberapa bidang sebagai kunci utama, maka indeks didasarkan pada bidang tersebut.

Sebagai contoh: Bidang A, B, C adalah kunci utama, jadi ketika Anda melakukan kueri berdasarkan 3 bidang tersebut di WHERE CLAUSE Anda, kinerjanya bagus, TETAPI ketika Anda ingin menanyakan dengan hanya bidang C di WHERE CLAUSE, Anda tidak akan mendapatkan kinerja yang baik. Jadi, untuk mendapatkan kinerja Anda dan berjalan, Anda perlu mengindeks kolom C secara manual.

Sering kali, Anda tidak akan melihat masalah hingga mencapai lebih dari 1 juta rekaman.


0

Saya memiliki database besar tanpa indeks (terpisah).

Setiap kali saya melakukan kueri dengan kunci utama, hasilnya, untuk semua tujuan intensif, instan.


Itu karena PK adalah indeks berkerumun, lihat paket kueri Anda
SQLMenace

0

kunci utama secara otomatis diindeks

Anda dapat membuat indeks tambahan menggunakan pk tergantung pada penggunaan Anda

  • index zip_code, id mungkin berguna jika Anda sering memilih dengan zip_code dan id
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.