Apakah ada perbedaan kinerja NYATA antara kunci primer INT dan VARCHAR?

174

Apakah ada perbedaan kinerja yang terukur antara menggunakan INT vs VARCHAR sebagai kunci utama di MySQL? Saya ingin menggunakan VARCHAR sebagai kunci utama untuk daftar referensi (pikirkan US States, Country Codes) dan rekan kerja tidak akan mengalah pada INT AUTO_INCREMENT sebagai kunci utama untuk semua tabel.

Argumen saya, sebagaimana dirinci di sini , adalah bahwa perbedaan kinerja antara INT dan VARCHAR dapat diabaikan, karena setiap referensi kunci asing INT akan memerlukan GABUNG untuk memahami referensi tersebut, kunci VARCHAR akan langsung menyajikan informasi.

Jadi, apakah ada yang punya pengalaman dengan kasus penggunaan khusus ini dan masalah kinerja yang terkait dengannya?

Jake McGraw
sumber
3
Saya membuat posting dengan jawaban "tidak" dengan beberapa tes yang telah saya jalankan ... tapi itu SQL Server, bukan MySQL. Jadi saya menghapus jawaban saya.
Timothy Khouri
17
@Timothy - Anda seharusnya tidak menghapusnya. Saya sedang dalam proses voting. Sebagian besar server database SQL memiliki perencana kueri yang sama dan hambatan kinerja yang serupa.
Paul Tomblin
9
@Timothy tolong kirim ulang hasil Anda.
Jake McGraw
2
Begitu banyak komentar dan jawaban mengasumsikan bahwa kunci ada untuk digunakan untuk bergabung. Mereka tidak. Kunci ada untuk digunakan untuk konsistensi data - untuk menghindari duplikasi baris, (lebih dari satu baris yang mewakili entitas yang sama). Setiap kolom (atau kumpulan kolom) dapat digunakan dalam suatu join, dan untuk menjamin bahwa join tersebut adalah satu ke nol atau banyak kolom [s] hanya perlu unik. Setiap indeks unik menjamin itu, dan itu tidak perlu bermakna.
Charles Bretana

Jawaban:

78

Anda membuat poin yang bagus bahwa Anda dapat menghindari sejumlah kueri yang digabungkan dengan menggunakan apa yang disebut kunci alami alih - alih kunci pengganti . Hanya Anda yang dapat menilai apakah manfaatnya signifikan dalam aplikasi Anda.

Artinya, Anda bisa mengukur kueri dalam aplikasi Anda yang paling penting untuk menjadi cepat, karena mereka bekerja dengan volume data yang besar atau dieksekusi sangat sering. Jika kueri ini mendapat manfaat dari menghilangkan gabungan, dan tidak menderita dengan menggunakan kunci utama varchar, maka lakukanlah.

Jangan gunakan salah satu strategi untuk semua tabel di database Anda. Kemungkinan dalam beberapa kasus, kunci alami lebih baik, tetapi dalam kasus lain kunci pengganti lebih baik.

Orang lain berpendapat bahwa jarang ada kunci alami yang tidak pernah berubah atau memiliki duplikat, jadi kunci pengganti biasanya bermanfaat.

Bill Karwin
sumber
3
Dan kadang-kadang, (imho, sering), keduanya lebih baik, pengganti untuk digunakan untuk referensi FK di tabel lain, dan untuk Bergabung, dan kunci alami untuk memastikan konsistensi data
Charles Bretana
@CharlesBretana Itu menarik. Apakah menggunakan kunci alami untuk konsistensi data di sepanjang sisi FK merupakan praktik yang umum? Pikiran pertama saya adalah bahwa penyimpanan ekstra yang diperlukan pada meja besar mungkin tidak menjadikannya bermanfaat. Setiap informasi dihargai. FYI - Saya memiliki latar belakang pemrograman yang baik tetapi pengalaman SQL saya terbatas sebagian besar untuk pertanyaan SELECT
Rob
2
@CharlesBretana Ketika saya membaca "simpan keduanya", saya pikir "redundansi" dan "tidak dinormalisasi", yang sama dengan "Barang ini bisa kacau" dan "Saya harus memastikan keduanya berubah jika ada yang berubah". Jika Anda memiliki redundansi, harus ada alasan yang sangat bagus (seperti kinerja yang sama sekali tidak dapat diterima) karena redundansi selalu berpotensi untuk data Anda menjadi tidak konsisten.
jpmc26
3
@ jpmc26, Sama sekali TIDAK ADA Masalah redundansi atau normalisasi. Kunci pengganti tidak memiliki koneksi yang berarti dengan nilai-nilai dalam kunci alami, sehingga tidak perlu diubah. Mengenai normalisasi, masalah normalisasi apa yang Anda bicarakan? Normalisasi berlaku untuk atribut yang bermakna dari suatu relasi; nilai numerik dari kunci pengganti, (tentu saja, konsep kunci pengganti itu sendiri) terletak sepenuhnya di luar konteks normalisasi.
Charles Bretana
1
Dan untuk menjawab pertanyaan Anda yang lain, khususnya tentang tabel negara, jika Anda memiliki kunci pengganti pada tabel ini, dengan nilai, katakanlah, frpom 1 hingga 50, tetapi Anda TIDAK menempatkan indeks atau kunci unik lain pada kode pos negara, (dan, menurut saya, pada nama negara juga), lalu apa yang menghentikan seseorang untuk memasukkan dua baris dengan nilai kunci pengganti yang berbeda tetapi dengan kode pos dan / atau nama negara yang sama? Bagaimana aplikasi klien menanganinya jika ada dua baris dengan 'NJ', 'New Jersey'? Natural Keys memastikan konsistensi data!
Charles Bretana
81

Ini bukan tentang kinerja. Ini tentang apa yang membuat kunci utama yang baik. Unik dan tidak berubah dari waktu ke waktu. Anda mungkin berpikir entitas seperti kode negara tidak pernah berubah seiring waktu dan akan menjadi kandidat yang baik untuk kunci utama. Tetapi pengalaman pahit jarang terjadi.

INT AUTO_INCREMENT memenuhi kondisi "unik dan tidak berubah dari waktu ke waktu". Karena itu preferensi.

Steve McLeod
sumber
25
Benar. Salah satu basis data terbesar saya memiliki entri untuk Yugoslavia dan Uni Soviet. Saya senang mereka bukan kunci utama.
Paul Tomblin
8
@Steve, lalu mengapa ANSI SQL mendukung sintaks untuk ON UPDATE CASCADE?
Bill Karwin
5
Kekekalan bukanlah persyaratan kunci. Bagaimanapun, kunci pengganti terkadang berubah juga. Tidak ada yang salah dengan mengganti kunci jika perlu.
nvogel
9
Paul, jadi Anda mengubah Uni Soviet ke Rusia di basis data Anda? Dan berpura-pura bahwa SU tidak pernah ada? Dan semua referensi SU sekarang menunjuk ke Rusia?
Dainius
6
@ alga saya lahir di SU jadi saya tahu apa itu.
Dainius
52

Saya agak terganggu oleh kurangnya tolok ukur untuk online ini, jadi saya menjalankan tes sendiri.

Perhatikan bahwa saya tidak melakukannya secara teratur, jadi silakan periksa pengaturan dan langkah-langkah saya untuk faktor-faktor yang dapat memengaruhi hasil secara tidak sengaja, dan kirimkan kekhawatiran Anda dalam komentar.

Setup adalah sebagai berikut:

  • Intel® Core ™ i7-7500U CPU @ 2.70GHz × 4
  • RAM 15,6 GiB, yang saya pastikan sekitar 8 GB gratis selama pengujian.
  • Drive SSD 148,6 GB, dengan banyak ruang kosong.
  • Ubuntu 16.04 64-bit
  • MySQL Ver 14.14 Distrib 5.7.20, untuk Linux (x86_64)

Tabel:

create table jan_int (data1 varchar(255), data2 int(10), myindex tinyint(4)) ENGINE=InnoDB;
create table jan_int_index (data1 varchar(255), data2 int(10), myindex tinyint(4), INDEX (myindex)) ENGINE=InnoDB;
create table jan_char (data1 varchar(255), data2 int(10), myindex char(6)) ENGINE=InnoDB;
create table jan_char_index (data1 varchar(255), data2 int(10), myindex char(6), INDEX (myindex)) ENGINE=InnoDB;
create table jan_varchar (data1 varchar(255), data2 int(10), myindex varchar(63)) ENGINE=InnoDB;
create table jan_varchar_index (data1 varchar(255), data2 int(10), myindex varchar(63), INDEX (myindex)) ENGINE=InnoDB;

Lalu, saya mengisi 10 juta baris di setiap tabel dengan skrip PHP yang intinya seperti ini:

$pdo = get_pdo();

$keys = [ 'alabam', 'massac', 'newyor', 'newham', 'delawa', 'califo', 'nevada', 'texas_', 'florid', 'ohio__' ];

for ($k = 0; $k < 10; $k++) {
    for ($j = 0; $j < 1000; $j++) {
        $val = '';
        for ($i = 0; $i < 1000; $i++) {
            $val .= '("' . generate_random_string() . '", ' . rand (0, 10000) . ', "' . ($keys[rand(0, 9)]) . '"),';
        }
        $val = rtrim($val, ',');
        $pdo->query('INSERT INTO jan_char VALUES ' . $val);
    }
    echo "\n" . ($k + 1) . ' millon(s) rows inserted.';
}

Untuk inttabel, bit ($keys[rand(0, 9)])diganti dengan adil rand(0, 9), dan untuk varchartabel, saya menggunakan nama negara bagian AS lengkap, tanpa memotong atau memperluasnya hingga 6 karakter. generate_random_string()menghasilkan string acak 10 karakter.

Lalu saya berlari di MySQL:

  • SET SESSION query_cache_type=0;
  • Untuk jan_intmeja:
    • SELECT count(*) FROM jan_int WHERE myindex = 5;
    • SELECT BENCHMARK(1000000000, (SELECT count(*) FROM jan_int WHERE myindex = 5));
  • Untuk tabel lain, sama seperti di atas, dengan myindex = 'califo'untuk chartabel dan myindex = 'california'untuk varchartabel.

Waktu BENCHMARKkueri di setiap tabel:

  • jan_int: 21,30 dtk
  • jan_int_index: 18,79 dtk
  • jan_char: 21,70 dtk
  • jan_char_index: 18,85 dtk
  • jan_varchar: 21,76 dtk
  • jan_varchar_index: 18,86 dtk

Mengenai ukuran tabel & indeks, inilah output dari show table status from janperformancetest;(dengan beberapa kolom tidak ditampilkan):

|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Name              | Engine | Version | Row_format | Rows    | Avg_row_length | Data_length | Max_data_length | Index_length | Data_free | Auto_increment | Collation              |
|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| jan_int           | InnoDB |      10 | Dynamic    | 9739094 |             43 |   422510592 |               0 |            0 |   4194304 |           NULL | utf8mb4_unicode_520_ci |  
| jan_int_index     | InnoDB |      10 | Dynamic    | 9740329 |             43 |   420413440 |               0 |    132857856 |   7340032 |           NULL | utf8mb4_unicode_520_ci |   
| jan_char          | InnoDB |      10 | Dynamic    | 9726613 |             51 |   500170752 |               0 |            0 |   5242880 |           NULL | utf8mb4_unicode_520_ci |  
| jan_char_index    | InnoDB |      10 | Dynamic    | 9719059 |             52 |   513802240 |               0 |    202342400 |   5242880 |           NULL | utf8mb4_unicode_520_ci |  
| jan_varchar       | InnoDB |      10 | Dynamic    | 9722049 |             53 |   521142272 |               0 |            0 |   7340032 |           NULL | utf8mb4_unicode_520_ci |   
| jan_varchar_index | InnoDB |      10 | Dynamic    | 9738381 |             49 |   486539264 |               0 |    202375168 |   7340032 |           NULL | utf8mb4_unicode_520_ci | 
|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|

Kesimpulan saya adalah bahwa tidak ada perbedaan kinerja untuk use case khusus ini.

Jan Żankowski
sumber
Saya tahu sudah terlambat sekarang, tetapi saya ingin tahu hasilnya jika Anda memilih string yang kurang ideal untuk kondisi di mana. "califo [rnia]" sangat ideal karena dapat membuang ketidakcocokan setelah membandingkan karakter pertama, hanya perlu memeriksa lebih lanjut pada pertandingan yang sebenarnya; sesuatu seperti "newham" akan memberikan hasil yang lebih menarik karena akan lebih baru untuk membandingkan lebih banyak karakter untuk menghilangkan semua ketidakcocokan. Juga, membatasi integer Anda dengan cara itu juga menumpuk peluang terhadap mereka, saya akan memberi mereka setidaknya 26 nilai.
Uueerdo
15
Luar biasa bahwa dalam pertanyaan berumur 10 tahun, ini hanya satu dari dua jawaban yang tidak hanya spekulasi dan bergantung pada tolok ukur yang sebenarnya.
Adrian Baker
1
Tetapi tabel Anda tidak memiliki kunci utama, yang sebenarnya di InnoDB adalah struktur data yang diurutkan. Kecepatan antara penyortiran bilangan bulat dan penyortiran string harus berbeda.
Melkor
1
@Melkor Fair point yang saya gunakan INDEXbukan PRIMARY KEY. Saya tidak ingat alasan saya - saya mungkin berasumsi PRIMARY KEYhanya INDEXdengan kendala keunikan. Namun, membaca bagian tentang bagaimana hal-hal disimpan di InnoDB di federico-razzoli.com/primary-key-in-innodb , saya pikir hasil saya masih berlaku untuk kunci utama, dan menjawab pertanyaan tentang perbedaan kinerja pencarian nilai. Juga, komentar Anda menyarankan melihat kinerja algoritma pengurutan , yang tidak berlaku untuk use case yang saya selidiki, yang mencari nilai dalam satu set.
Jan Żankowski
1
Operasi pencarian juga membutuhkan perbandingan pada bidang kunci utama (seperti pencarian biner), di mana int harusnya sedikit lebih cepat daripada varchar. Tetapi seperti yang disarankan percobaan Anda, itu tidak begitu jelas (atau mungkin karena Anda tidak memiliki kunci utama sehingga semua pertanyaan lebih lambat). Saya pikir itu hal yang sama pada memasukkan dan mencari.
Melkor
38

Tergantung pada panjangnya .. Jika varchar akan menjadi 20 karakter, dan int adalah 4, maka jika Anda menggunakan int, indeks Anda akan memiliki LIMA kali lebih banyak node per halaman ruang indeks pada disk ... Itu berarti bahwa melintasi indeks akan membutuhkan seperlima dari banyak pembacaan fisik dan / atau logis ..

Jadi, jika kinerja merupakan masalah, diberi kesempatan, selalu gunakan kunci integral yang tidak bermakna (disebut pengganti) untuk tabel Anda, dan untuk Kunci Asing yang mereferensikan baris dalam tabel ini ...

Pada saat yang sama , untuk menjamin konsistensi data, setiap tabel yang penting juga harus memiliki kunci alternatif non-numerik yang berarti, (atau Indeks unik) untuk memastikan bahwa baris duplikat tidak dapat dimasukkan (duplikat berdasarkan atribut tabel yang bermakna).

Untuk penggunaan spesifik yang Anda bicarakan (seperti pencarian negara bagian) itu benar-benar tidak masalah karena ukuran tabelnya sangat kecil .. Secara umum tidak ada dampak pada kinerja dari indeks pada tabel dengan kurang dari beberapa ribu baris. ..

Charles Bretana
sumber
Tentu? Bukankah kebanyakan format data berbasis baris? Ada data lain selain kunci. Bukankah faktor 5 utopis?
ManuelSchneid3r
1
@ manuelSchneid3r, Apa? utopis? Tidak, faktor 5 bukan "utopis". Ini hanya 20 dibagi dengan 4. Dan apa artinya "berbasis format data baris"? Indeks tidak "berdasarkan baris", mereka adalah struktur pohon yang seimbang.
Charles Bretana
36

Benar-benar tidak.

Saya telah melakukan beberapa ... beberapa ... pemeriksaan kinerja antara INT, VARCHAR, dan CHAR.

Meja catatan 10 juta dengan KUNCI UTAMA (unik dan berkerumun) memiliki kecepatan dan kinerja yang sama persis (dan biaya subtree) tidak peduli mana dari tiga yang saya gunakan.

Yang sedang berkata ... gunakan apa pun yang terbaik untuk aplikasi Anda. Jangan khawatir tentang kinerjanya.

Timothy Khouri
sumber
42
tidak berarti tanpa mengetahui berapa lama varchars itu ... Jika mereka adalah 100 byte widem maka dijamin Anda tidak akan mendapatkan kinerja yang sama dengan int 4 byte
Charles Bretana
6
Ini juga akan membantu untuk mengetahui database apa yang Anda gunakan dan versi database apa. Penyesuaian kinerja hampir selalu berhasil dan ditingkatkan dari versi ke versi.
Dave Black
VARCHAR jelas penting untuk ukuran indeks. Dan indeks menentukan berapa banyak yang bisa muat dalam memori. Dan indeks dalam memori jauh, jauh lebih cepat daripada yang tidak. Bisa jadi untuk baris 10m Anda, Anda memiliki 250MB memori yang tersedia untuk indeks itu, dan baik-baik saja. Tetapi jika Anda memiliki 100m baris, Anda akan kurang baik dalam memori itu.
Paul Draper
9

Untuk kode pendek, mungkin tidak ada perbedaan. Ini terutama benar karena tabel yang menyimpan kode-kode ini cenderung sangat kecil (paling banyak dua ribu baris) dan tidak sering berubah (kapan terakhir kali kami menambahkan Negara Bagian AS yang baru).

Untuk tabel yang lebih besar dengan variasi yang lebih luas di antara kunci, ini bisa berbahaya. Pikirkan tentang menggunakan alamat email / nama pengguna dari tabel Pengguna, misalnya. Apa yang terjadi ketika Anda memiliki beberapa juta pengguna dan beberapa dari pengguna tersebut memiliki nama panjang atau alamat email. Sekarang kapan saja Anda perlu bergabung dengan tabel ini menggunakan kunci itu menjadi jauh lebih mahal.

Joel Coehoorn
sumber
2
Apakah Anda tahu pasti bahwa ini akan mahal? Atau Anda hanya menebak?
Steve McLeod
Tentu saja itu tergantung pada implementasi rdbms, tetapi dari apa yang saya pahami kebanyakan server akan menyimpan hash dari nilai aktual untuk keperluan pengindeksan. Meski begitu, dan bahkan jika itu adalah hash yang relatif singkat (katakanlah, 10 byte), masih lebih berfungsi untuk membandingkan hash 2 10 byte dari 2 int 4 byte.
Joel Coehoorn
JANGAN PERNAH menggunakan kunci panjang (lebar) untuk bergabung ... Tetapi jika itu adalah representasi terbaik dari apa yang unik untuk baris dalam tabel, maka lebih baik ada kunci unik (atau indeks - yang merupakan hal yang sama) pada tabel menggunakan nilai-nilai alami tersebut. Tidak ada kunci untuk bergabung, Anda dapat bergabung dengan apa pun yang diinginkan hati Anda. Kunci ada untuk memastikan konsistensi data.
Charles Bretana
6

Adapun Kunci Utama, apa pun yang secara fisik membuat baris unik harus ditentukan sebagai kunci utama.

Untuk referensi sebagai kunci asing, menggunakan integer penambahan otomatis sebagai pengganti adalah ide yang bagus karena dua alasan utama.
- Pertama, biasanya ada lebih sedikit overhead yang terjadi pada join.
- Kedua, jika Anda perlu memperbarui tabel yang berisi varchar unik maka pembaruan harus mengalir ke semua tabel anak dan memperbarui semuanya serta indeks, sedangkan dengan pengganti int, hanya perlu memperbarui tabel master dan itu indeks.

Alasan untuk menggunakan pengganti adalah bahwa Anda mungkin dapat mengizinkan perubahan arti pengganti:

ex.
id value
1 A
2 B
3 C

Update 3 to D
id value
1 A
2 B
3 D

Update 2 to C
id value
1 A
2 C
3 D

Update 3 to B
id value
1 A
2 C
3 B

Itu semua tergantung pada apa yang Anda benar-benar perlu khawatirkan dalam struktur Anda dan apa yang paling berarti.

LeppyR64
sumber
3

Kasus umum di mana pengganti AUTO_INCREMENT sakit:

Pola skema umum adalah pemetaan banyak-ke-banyak :

CREATE TABLE map (
    id ... AUTO_INCREMENT,
    foo_id ...,
    bar_id ...,
    PRIMARY KEY(id),
    UNIQUE(foo_id, bar_id),
    INDEX(bar_id) );

Performa dari pola ini jauh lebih baik, terutama ketika menggunakan InnoDB:

CREATE TABLE map (
    # No surrogate
    foo_id ...,
    bar_id ...,
    PRIMARY KEY(foo_id, bar_id),
    INDEX      (bar_id, foo_id) );

Mengapa?

  • Kunci sekunder InnoDB membutuhkan pencarian ekstra; dengan memindahkan pasangan ke PK, yang dihindari untuk satu arah.
  • Indeks sekunder adalah "meliputi", sehingga tidak perlu pencarian tambahan.
  • Tabel ini lebih kecil karena menyingkirkan iddan satu indeks.

Kasus lain ( negara ):

country_id INT ...
-- versus
country_code CHAR(2) CHARACTER SET ascii

Terlalu sering, pemula menormalkan country_code menjadi 4-byte INTalih - alih menggunakan string 2-byte yang alami, hampir-tidak berubah. Lebih cepat, lebih kecil, lebih sedikit GABUNG, lebih mudah dibaca.

Rick James
sumber
2

Di HauteLook, kami mengubah banyak tabel kami untuk menggunakan kunci alami. Kami memang mengalami peningkatan kinerja di dunia nyata. Seperti yang Anda sebutkan, banyak pertanyaan kami sekarang menggunakan lebih sedikit gabungan yang membuat kueri lebih berkinerja. Kami bahkan akan menggunakan kunci primer komposit jika masuk akal. Yang sedang berkata, beberapa tabel hanya lebih mudah untuk bekerja dengan jika mereka memiliki kunci pengganti.

Juga, jika Anda membiarkan orang menulis antarmuka ke basis data Anda, kunci pengganti dapat membantu. Pihak ketiga dapat mengandalkan fakta bahwa kunci pengganti hanya akan berubah dalam keadaan yang sangat jarang.

Herman J. Radtke III
sumber
2

Saya menghadapi dilema yang sama. Saya membuat DW (skema Constellation) dengan 3 tabel fakta, Kecelakaan di Jalan, Kendaraan dalam Kecelakaan dan Korban dalam Kecelakaan. Data mencakup semua kecelakaan yang tercatat di Inggris dari tahun 1979 hingga 2012, dan tabel 60 dimensi. Secara keseluruhan, sekitar 20 juta catatan.

Tabel fakta hubungan:

+----------+          +---------+
| Accident |>--------<| Vehicle |
+-----v----+ 1      * +----v----+
     1|                    |1
      |    +----------+    |
      +---<| Casualty |>---+
         * +----------+ *

RDMS: MySQL 5.6

Secara native, indeks Kecelakaan adalah varchar (angka dan huruf), dengan 15 digit. Saya mencoba untuk tidak memiliki kunci pengganti, begitu indeks kecelakaan tidak akan pernah berubah. Di komputer i7 (8 core), DW menjadi terlalu lambat untuk diminta setelah 12 juta catatan beban tergantung dari dimensinya. Setelah banyak bekerja kembali dan menambahkan kunci pengganti bigint, saya mendapat peningkatan kinerja kecepatan rata-rata 20%. Belum mendapatkan kinerja yang rendah, tetapi coba valid. Saya bekerja di tuning dan clustering MySQL.

Diego Duarte
sumber
1
Kedengarannya seperti Anda perlu melihat ke partisi.
jcoffland
2

Pertanyaannya adalah tentang MySQL, jadi saya katakan ada perbedaan yang signifikan. Jika itu tentang Oracle (yang menyimpan angka sebagai string - ya, saya tidak percaya pada awalnya) maka tidak banyak perbedaan.

Penyimpanan dalam tabel bukan masalah tetapi memperbarui dan mengacu pada indeks. Kueri yang melibatkan pencarian catatan berdasarkan kunci primernya sering - Anda ingin itu terjadi secepat mungkin karena sering terjadi.

Masalahnya adalah penawaran CPU dengan 4 byte dan 8 byte integer secara alami, dalam silikon . Ini BENAR-BENAR cepat untuk membandingkan dua bilangan bulat - ini terjadi dalam satu atau dua siklus clock.

Sekarang lihat string - terdiri dari banyak karakter (lebih dari satu byte per karakter hari ini). Membandingkan dua string untuk diutamakan tidak dapat dilakukan dalam satu atau dua siklus. Sebaliknya karakter string harus diulang sampai perbedaan ditemukan. Saya yakin ada trik untuk membuatnya lebih cepat di beberapa database tapi itu tidak relevan di sini karena perbandingan int dilakukan secara alami dan kilat cepat dalam silikon oleh CPU.

Aturan umum saya - setiap kunci utama harus merupakan INT peningkatan otomatis terutama di aplikasi OO menggunakan ORM (Hibernate, Datanucleus, apa pun) di mana ada banyak hubungan antara objek - biasanya akan selalu diimplementasikan sebagai FK sederhana dan kemampuan untuk DB untuk menyelesaikannya dengan cepat penting untuk responsif aplikasi Anda.

Volksman
sumber
0

Tidak yakin tentang implikasi kinerja, tetapi tampaknya kompromi yang mungkin, setidaknya selama pengembangan, adalah memasukkan kunci "pengganti" integer yang ditambahkan secara otomatis, serta kunci yang Anda inginkan, unik, "alami". Ini akan memberi Anda kesempatan untuk mengevaluasi kinerja, serta masalah-masalah lain yang mungkin terjadi, termasuk perubahan kemampuan kunci alami.

Dexygen
sumber
0

Seperti biasa, tidak ada jawaban. 'Tergantung!' dan saya tidak bercanda. Pemahaman saya tentang pertanyaan awal adalah kunci pada tabel kecil - seperti Negara (bilangan bulat id atau kode char / varchar) menjadi kunci asing ke tabel berpotensi besar seperti tabel alamat / kontak.

Ada dua skenario di sini ketika Anda ingin data kembali dari DB. Pertama adalah daftar / jenis pencarian kueri di mana Anda ingin membuat daftar semua kontak dengan kode atau nama negara dan negara (id tidak akan membantu dan karenanya perlu pencarian). Yang lainnya adalah skenario get pada kunci utama yang menunjukkan catatan kontak tunggal di mana nama negara, negara perlu ditampilkan.

Untuk mendapatkan yang terakhir, mungkin tidak masalah apa yang menjadi dasar FK karena kita mengumpulkan tabel untuk satu catatan atau beberapa catatan dan pada bacaan utama. Skenario sebelumnya (pencarian atau daftar) dapat dipengaruhi oleh pilihan kami. Karena diharuskan menunjukkan negara (setidaknya kode yang dapat dikenali dan mungkin bahkan pencarian itu sendiri termasuk kode negara), tidak harus bergabung dengan tabel lain melalui kunci pengganti dapat berpotensi (saya hanya berhati-hati di sini karena saya belum benar-benar menguji ini, tetapi tampaknya sangat mungkin) meningkatkan kinerja; terlepas dari kenyataan bahwa itu pasti membantu pencarian.

Karena kode berukuran kecil - tidak lebih dari 3 karakter biasanya untuk negara dan negara, mungkin boleh saja menggunakan kunci alami sebagai kunci asing dalam skenario ini.

Skenario lain di mana kunci bergantung pada nilai varchar yang lebih panjang dan mungkin pada tabel yang lebih besar; kunci pengganti mungkin memiliki keunggulan.

Vinod
sumber
0

Izinkan saya untuk mengatakan ya pasti ada perbedaan, dengan mempertimbangkan lingkup kinerja (Definisi di luar kotak):

1- Menggunakan surrogate int lebih cepat dalam aplikasi karena Anda tidak perlu menggunakan ToUpper (), ToLower (), ToUpperInvarient (), atau ToLowerInvarient () dalam kode Anda atau dalam kueri Anda dan 4 fungsi ini memiliki tolok ukur kinerja yang berbeda. Lihat aturan kinerja Microsoft tentang ini. (kinerja aplikasi)

2- Menggunakan pengganti pengganti tidak mengubah kunci dari waktu ke waktu. Bahkan kode negara dapat berubah, lihat Wikipedia bagaimana kode ISO berubah dari waktu ke waktu. Itu akan membutuhkan banyak waktu untuk mengubah kunci utama untuk sub cabang. (kinerja pemeliharaan data)

3 - Tampaknya ada masalah dengan solusi ORM, seperti NHibernate ketika PK / FK tidak int. (kinerja pengembang)

Shadi Namrouti
sumber