String sebagai Kunci Utama dalam Database SQL

178

Saya tidak terlalu mengenal database dan teori di balik cara kerjanya. Apakah ada yang lebih lambat dari sudut pandang kinerja (memasukkan / memperbarui / query) untuk menggunakan Strings untuk Kunci Utama daripada bilangan bulat?

mainstringargs
sumber

Jawaban:

191

Secara teknis ya, tetapi jika sebuah string masuk akal untuk menjadi kunci utama maka Anda mungkin harus menggunakannya. Ini semua tergantung pada ukuran tabel yang Anda buat dan panjang string yang akan menjadi kunci utama (string lebih panjang == lebih sulit untuk dibandingkan). Saya tidak perlu menggunakan string untuk tabel yang memiliki jutaan baris, tetapi jumlah pelambatan kinerja yang Anda dapatkan dengan menggunakan string pada tabel yang lebih kecil akan sangat kecil untuk sakit kepala yang dapat Anda miliki dengan memiliki bilangan bulat yang tidak berarti apa pun dalam kaitannya dengan data.

kemiller2002
sumber
11
bukankah itu tergantung pada database? Saya akan berpikir string yang diindeks dengan benar tidak akan jauh lebih lambat jika sama sekali dari nomor?
Ryan Guill
2
Saya setuju ada banyak variabel untuk dipertimbangkan. (Dalam sqlserver) kita telah melihat masalah kinerja nyata dengan menggunakan string dengan panjang di pertengahan hingga remaja tinggi dan di atas bahkan ketika diindeks. Beli Anda benar ada beberapa hal untuk mengatasi perangkat keras ini misalnya.
kemiller2002
1
Cukup adil. Saya akan setuju bahwa jika string masuk akal, itulah yang harus Anda gunakan. Saya juga akan mengatakan pasti ada waktu untuk bidang GUID atau UUID di database di mana bidang autoincrement tidak akan berfungsi.
Ryan Guill
7
Juga perlu diingat bahwa sering kali ada perbedaan yang sangat besar antara CHAR dan VARCHAR ketika melakukan perbandingan indeks
Tom H
7
Jumlah komentar dari jawaban ini menjelaskan betapa tidak lengkapnya jawaban itu. Menyebutkan pengindeksan akan menjadi jawaban minimum yang dapat diterima.
Pedro Rolo
74

Masalah lain dengan menggunakan Strings sebagai kunci utama adalah bahwa karena indeks terus-menerus dimasukkan ke dalam urutan berurutan, ketika kunci baru dibuat yang akan berada di tengah urutan indeks harus di-resequenced ... jika Anda menggunakan otomatis angka integer, kunci baru baru saja ditambahkan ke akhir indeks.

Jeff Martin
sumber
2
Ini dapat menyebabkan "hot spot" untuk sisipan baru. Selama Anda mengelola basis data dengan benar, Anda tetap harus memiliki ruang ekstra pada halaman untuk memasukkan dan pemisahan halaman harus jarang terjadi.
Tom H
20
saat itulah kunci utama dikelompokkan. Anda dapat membuatnya juga tidak terpecah.
Belajar
XID dipesan yang mungkin membantu jika Anda hanya menggunakan string xid
Sinaesthetic
22

Menyisipkan tabel yang memiliki indeks berkerumun di mana penyisipan terjadi di tengah urutan TIDAK menyebabkan indeks ditulis ulang. Itu tidak menyebabkan halaman yang terdiri dari data ditulis ulang. Jika ada ruang pada halaman di mana baris akan pergi, maka ditempatkan di halaman itu. Halaman tunggal akan diformat ulang untuk menempatkan baris di tempat yang tepat di halaman. Ketika halaman penuh, satu halaman akan terjadi, dengan setengah dari baris di halaman menuju ke satu halaman, dan setengah di yang lain. Halaman-halaman tersebut kemudian dihubungkan kembali ke daftar halaman yang terhubung yang terdiri dari tabel data yang memiliki indeks berkerumun. Paling-paling, Anda akhirnya akan menulis 2 halaman basis data.

Mark Thompson
sumber
Penjelasan yang bagus. Tetapi apakah ini benar untuk semua database SQL? Saya pernah mendengar masalah kinerja MySQL saat menggunakan UUID acak sebagai kunci utama.
hgoebl
13

String lebih lambat bergabung dan dalam kehidupan nyata mereka sangat jarang benar-benar unik (bahkan ketika mereka seharusnya). Satu-satunya keuntungan adalah mereka dapat mengurangi jumlah gabungan jika Anda bergabung ke tabel utama hanya untuk mendapatkan namanya. Namun, string juga sering berubah sehingga menciptakan masalah karena harus memperbaiki semua catatan terkait ketika nama perusahaan berubah atau orang tersebut menikah. Ini bisa menjadi hit kinerja besar dan jika semua tabel yang harus terkait entah bagaimana tidak terkait (ini terjadi lebih sering daripada yang Anda pikirkan), maka Anda mungkin memiliki ketidakcocokan data juga. Integer yang tidak akan pernah berubah sepanjang usia catatan adalah pilihan yang jauh lebih aman dari sudut pandang integritas data maupun dari sudut pandang kinerja. Kunci alami biasanya tidak begitu baik untuk pemeliharaan data.

Saya juga ingin menunjukkan bahwa yang terbaik dari kedua dunia sering menggunakan kunci peningkatan otomatis (atau dalam beberapa kasus khusus, GUID) sebagai PK dan kemudian menempatkan indeks unik pada kunci alami. Anda mendapatkan bergabung lebih cepat, Anda tidak mendapatkan duplikat catatan, dan Anda tidak perlu memperbarui sejuta catatan anak karena nama perusahaan berubah.

HLGEM
sumber
26
String yang merupakan kandidat yang baik untuk PK tidak memiliki duplikat - jika tidak mereka tidak akan menjadi kandidat yang baik untuk PK. Pikirkan kode ICD-9, kode negara, VIN #s. Menggunakan nama sebagai contoh masalah dengan kunci alami salah arah, karena mereka tidak boleh menjadi kandidat.
Tom H
6
@ Tom H: Kode County ISO DO berubah. [ en.wikipedia.org/wiki/ISO_3166-1#Editions_and_changes ] Sebagai jawaban atas pertanyaan terkait, katakan [ stackoverflow.com/questions/925266/… ] "Untuk PRIMARY KEY, pastikan keunikan mereka ada di bawah kendali Anda"
Steve Schnepp
4
@SteveSchnepp: ya dan ISO adalah badan tepercaya untuk mengelola perubahan itu. Di sisi lain, ketika Anda perlu menggabungkan urutan monoton kenaikan nilai integer dengan nilai orang lain, Anda berada pada Anda sendiri;)
onedaywhen
1
Saya akan setuju bahwa nama-nama tidak boleh dianggap sebagai kunci, saya baru saja melihat banyak waktu ketika mereka.
HLGEM
1
@oneday ketika menggabungkan 2 urutan monoton penambahan bilangan bulat cukup mudah dilakukan melalui awalan atau akhiran :)
Steve Schnepp
6

Tidak masalah apa yang Anda gunakan sebagai kunci utama selama itu UNIK. Jika Anda peduli tentang kecepatan atau desain database yang baik gunakan int kecuali Anda berencana mereplikasi data, kemudian gunakan GUID.

Jika ini adalah database akses atau aplikasi kecil maka siapa yang benar-benar peduli. Saya pikir alasan mengapa sebagian besar dari kita pengembang menampar int atau panduan lama di depan adalah karena proyek memiliki cara untuk tumbuh pada kami, dan Anda ingin meninggalkan sendiri pilihan untuk tumbuh.

Al Katawazi
sumber
5

Terlalu banyak variabel. Itu tergantung pada ukuran tabel, indeks, sifat dari domain kunci string ...

Secara umum , bilangan bulat akan lebih cepat. Tetapi apakah perbedaannya cukup besar untuk diperhatikan? Sulit dikatakan.

Juga, apa motivasi Anda untuk memilih string? Tombol peningkatan otomatis numerik seringkali jauh lebih mudah juga. Apakah itu semantik? Kenyamanan? Replikasi / keprihatinan terputus? Jawaban Anda di sini dapat membatasi opsi Anda. Ini juga mengingatkan opsi "hibrid" ketiga yang Anda lupa: Panduan.

Joel Coehoorn
sumber
itu tidak masuk akal cloutierm, apa maksudmu?
HLGEM
@ HLGEM: Jika saya mengerti dia menulis, maksudnya seperti menyinkronkan catatan yang dibuat pada laptop dengan db utama.
Joel Coehoorn
Maksud saya, saya memiliki dua basis data terpisah dengan entitas yang sama, hanya satu yang lebih jarang diperbarui untuk tujuan penyimpanan persisten. Jika saya Query untuk entitas "California" pada Database A, saya ingin secara fundamental sama "California" pada Database B.
mainstringargs
1
Dan itu 'seperti' menyinkronkan catatan yang dibuat di laptop dengan masalah yang sama: catatan yang dibuat di satu tempat tidak boleh bertentangan dengan catatan yang dibuat di tempat lain. Salah satu solusi yang mungkin di sini adalah kunci panduan.
Joel Coehoorn
5

Jangan khawatir tentang kinerja sampai Anda memiliki desain sederhana dan suara yang sesuai dengan pokok bahasan yang dideskripsikan dan cocok dengan tujuan penggunaan data. Kemudian, jika masalah kinerja muncul, Anda dapat mengatasinya dengan mengubah sistem.

Dalam hal ini, hampir selalu lebih baik menggunakan string sebagai kunci primer alami, asalkan Anda bisa memercayainya. Jangan khawatir jika itu adalah string, asalkan string tersebut cukup pendek, katakanlah sekitar 25 karakter maks. Anda tidak akan membayar harga yang besar dalam hal kinerja.

Apakah orang entri data atau sumber data otomatis selalu memberikan nilai untuk kunci alami yang seharusnya, atau kadang-kadang dihilangkan? Apakah sesekali salah dalam input data? Jika demikian, bagaimana kesalahan terdeteksi dan diperbaiki?

Apakah pemrogram dan pengguna interaktif yang menentukan kueri dapat menggunakan kunci alami untuk mendapatkan yang mereka inginkan?

Jika Anda tidak dapat mempercayai kunci alami, ciptakan pengganti. Jika Anda membuat pengganti, Anda mungkin juga menemukan integer. Maka Anda harus khawatir tentang di mana untuk menyembunyikan pengganti dari komunitas pengguna. Beberapa pengembang yang tidak menyembunyikan kunci pengganti datang untuk menyesalinya.

Walter Mitty
sumber
3

Indeks menyiratkan banyak perbandingan.

Biasanya, string lebih panjang daripada bilangan bulat dan aturan pemeriksaan dapat diterapkan untuk perbandingan, jadi membandingkan string biasanya lebih intensif secara komputasi daripada membandingkan bilangan bulat.

Namun, kadang-kadang, lebih cepat menggunakan string sebagai kunci utama daripada membuat gabung tambahan dengan string to numerical idtabel.

Quassnoi
sumber
2

Ya, tetapi kecuali Anda berharap memiliki jutaan baris, tidak menggunakan kunci berbasis string karena lebih lambat biasanya "optimasi prematur." Bagaimanapun, string disimpan sebagai angka besar sedangkan kunci numerik biasanya disimpan sebagai angka yang lebih kecil.

Satu hal yang harus diperhatikan, adalah jika Anda telah mengelompokkan indeks pada kunci apa pun dan melakukan sejumlah besar sisipan yang tidak berurutan dalam indeks. Setiap baris yang ditulis akan menyebabkan indeks untuk menulis ulang. jika Anda melakukan batch insert, ini benar-benar dapat memperlambat proses.

Ya - Jake itu.
sumber
2

Dua alasan untuk menggunakan bilangan bulat untuk kolom PK:

  1. Kita dapat menetapkan identitas untuk bidang bilangan bulat yang bertambah secara otomatis.

  2. Ketika kita membuat PK, db membuat indeks (Cluster atau Non Cluster) yang mengurutkan data sebelum disimpan dalam tabel. Dengan menggunakan identitas pada PK, pengoptimal tidak perlu memeriksa urutan pengurutan sebelum menyimpan catatan. Ini meningkatkan kinerja pada tabel besar.

Jatinder Singh
sumber
1

Apa alasan Anda memiliki string sebagai kunci utama?

Saya hanya akan mengatur kunci utama ke bidang integer kenaikan otomatis, dan menempatkan indeks pada bidang string.

Dengan begitu jika Anda melakukan pencarian di atas meja mereka harus relatif cepat, dan semua bergabung Anda dan pencarian normal akan tidak terpengaruh dalam kecepatan mereka.

Anda juga dapat mengontrol jumlah bidang string yang diindeks. Dengan kata lain, Anda dapat mengatakan "hanya mengindeks 5 karakter pertama" jika Anda merasa cukup. Atau jika data Anda bisa relatif sama, Anda bisa mengindeks seluruh bidang.

John Bubriski
sumber
3
Saya pikir menempatkan kecerdasan apa pun di kunci adalah meminta masalah. Apakah mereka akan tetap unik? Apakah mereka memulai semua nomor akun dengan singkatan negara pada mulanya hanya untuk perpindahan klien. Perbarui bidang - tidak masalah - semua tabel yang ditautkan oleh nomor akun - berantakan.
JeffO
1
Contoh menggunakan string sebagai PK bisa berupa tabel pengaturan. mis. settingNamePK, isUserEditable, isCustomerEditable dll. Lalu jika Anda ingin memodifikasi perilaku pengaturan "SET pengaturan UPDATE ... WHERE settingNamePK = 'dailyWorkObligation'" jauh lebih bagus daripada harus menggunakan ID dan menyimpan di suatu tempat pemetaan ID. Tentu saja Anda bisa memiliki integer PK dan memiliki nama pengaturan sebagai kunci unik lainnya.
MeatPopsicle
Dengan kunci utama menjadi bilangan bulat yang ditingkatkan secara otomatis, bukankah masukkan juga tidak terpengaruh dalam kecepatannya?
Dennis
Untuk pengembang Rails yang penasaran, berikut ini cara menentukan panjang indeks . Perhatikan bahwa SQLite tidak mendukung panjang indeks.
Dennis
1

Dari sudut pandang kinerja - Ya string (PK) akan memperlambat kinerja bila dibandingkan dengan kinerja yang dicapai menggunakan integer (PK), di mana PK ---> Primary Key.

Dari sudut pandang persyaratan - Meskipun ini bukan bagian dari pertanyaan Anda, saya tetap ingin menyebutkan. Saat kami menangani data besar di berbagai tabel, kami biasanya mencari set kunci yang mungkin dapat diatur untuk tabel tertentu. Ini terutama karena ada banyak tabel dan sebagian besar masing-masing atau beberapa tabel akan terkait dengan yang lain melalui beberapa hubungan (konsep Foreign Key). Oleh karena itu kita benar-benar tidak selalu dapat memilih integer sebagai Kunci Utama, melainkan kita pergi untuk kombinasi 3, 4 atau 5 atribut sebagai kunci utama untuk tabel itu. Dan kunci-kunci itu dapat digunakan sebagai kunci asing ketika kita akan menghubungkan catatan dengan beberapa tabel lainnya. Ini berguna untuk menghubungkan rekaman di berbagai tabel bila diperlukan.

Karenanya untuk Penggunaan Optimal - Kami selalu membuat kombinasi 1 atau 2 bilangan bulat dengan atribut 1 atau 2 string, tetapi sekali lagi hanya jika diperlukan.


sumber
0

Mungkin ada kesalahpahaman yang sangat besar terkait dengan string dalam database tersebut. Hampir semua orang mengira bahwa representasi basis data dari angka lebih kompak daripada untuk string. Mereka berpikir bahwa angka db-s direpresentasikan dalam memori. TAPI itu tidak benar. Dalam kebanyakan kasus, representasi angka lebih dekat dengan string seperti representasi daripada yang lain.

Kecepatan menggunakan angka atau string lebih tergantung pada pengindeksan daripada jenis itu sendiri.

takacsot
sumber
0

Secara default ASPNetUserIds adalah 128 string char dan kinerjanya baik-baik saja.

Jika kunci HARUS unik di tabel itu harus Kunci. Inilah alasannya;

primary string key = Hubungan DB yang benar, 1 string kunci (Utama), dan 1 string Indeks (Utama).

Opsi lainnya adalah Kunci int khas, tetapi jika string HARUS unik, Anda mungkin masih perlu menambahkan indeks karena permintaan non-stop untuk memvalidasi atau memeriksa apakah unik.

Jadi menggunakan int identity key = Hubungan DB yang salah, 1 int key (Primer), 1 int index (Primer), Mungkin indeks string unik, dan secara manual harus memvalidasi string yang sama tidak ada (sesuatu seperti cek sql mungkin ).

Untuk mendapatkan kinerja yang lebih baik menggunakan int di atas string untuk kunci utama, ketika string HARUS unik, itu harus menjadi situasi yang sangat aneh. Saya selalu lebih suka menggunakan kunci string. Dan sebagai aturan praktis yang baik, jangan mendenormalkan database sampai Anda PERLU .

JPoole
sumber