Mengapa penggunaan kunci string umumnya dianggap sebagai ide yang buruk?

24

Ini telah menggangguku untuk sementara waktu. Sebagian besar waktu, ketika datang untuk menyimpan data dalam struktur seperti hashtables, programer, buku dan artikel bersikeras bahwa pengindeksan elemen dalam struktur tersebut dengan nilai String dianggap praktik yang buruk. Namun, sejauh ini, saya belum menemukan satu pun sumber seperti itu untuk menjelaskan mengapa itu dianggap praktik yang buruk. Apakah ini tergantung pada bahasa pemrograman? Pada kerangka kerja yang mendasarinya? Tentang implementasinya?

Ambil dua contoh sederhana, jika itu membantu:

Tabel seperti SQL tempat baris diindeks oleh kunci primer String.

Kamus .NET di mana tombolnya adalah Strings.


sumber
9
Memiliki kunci string bukanlah ide yang buruk secara umum. Saya menduga pernyataan itu dibuat dalam konteks di mana jenis kunci yang lebih baik tersedia. Saya memiliki kamus .net dengan kunci string sepanjang waktu. Bisakah Anda memberikan beberapa contoh klaim ini?
CodesInChaos
3
Anda biasanya menginginkan kunci utama yang tidak berubah selama masa objek / baris. Jadi misalnya usernamesebagai kunci utama userstabel mungkin bukan ide terbaik, dan Anda lebih suka id kenaikan otomatis. Tapi itu usernameadalah string yang hanya bersifat insidentil, menjadi properti yang bisa berubah adalah masalah utama
CodesInChaos
Dalam basis data, pertimbangkan bagaimana cara mengindeks string sebagai lawan bilangan bulat.
@CodesInChaos Saya berharap saya bisa mengingat di mana saya menemukan sebagian besar kasus, tetapi untuk sekarang saya dapat menempelkan bit yang mengingatkan saya pada masalah ini. Itu dari tayangan slide GDC oleh Valve yang membahas dialog game dan menyimpan fakta tentang dunia dalam pasangan <key = string, value = object>.
2
String baik-baik saja. Hanya saja bukan string 'ajaib'. Jadi, ketika menggunakan tabel hash, pastikan Anda tidak memiliki string telanjang di kode Anda. Anda harus menghindari nilai teks besar sebagai kunci karena tidak berkinerja baik, tetapi dalam kebanyakan situasi dunia nyata string teks pendek sama cepatnya dengan integer (mereka bukan basis data masif). Anda juga dapat menggunakan kunci alternatif, misalnya, kunci utama adalah angka tetapi ada juga string 'siput' atau unik yang juga unik.
ipaul

Jawaban:

17

Itu semua ada hubungannya dengan dua hal pada dasarnya:

1) Kecepatan pencarian (di mana bilangan bulat misalnya ongkos jauh lebih baik)

2) Ukuran indeks (di mana indeks string akan meledak)

Sekarang semuanya tergantung pada kebutuhan Anda dan ukuran dataset. Jika tabel atau kumpulan memiliki 10-20 elemen di dalamnya, jenis kuncinya tidak relevan. Ini akan sangat cepat bahkan dengan kunci string.

PS Mungkin tidak terkait dengan pertanyaan Anda, tetapi Panduan dianggap buruk untuk kunci basis data juga (16 byte Guid vs 4 byte integer). Pada volume data yang besar Panduan harus memperlambat pencarian.

kelinci
sumber
Tidak selalu - GUID tambahan mungkin dilakukan. Indeks masih akan lebih besar, tetapi hukuman pencarian tidak akan seburuk itu.
Sam
7
Sebenarnya mereka baik-baik saja. Anda harus melihat hubungan antara waktu disk IO waktu dan membandingkan nilai dalam memori. Karena waktu akses disk melebihi perbandingan memori, satu-satunya hal yang sangat penting dalam menganalisis kinerja database adalah IO. Apakah kuncinya adalah GUID, string atau integer tidak terlalu penting. Ukuran indeks memengaruhi berapa banyak nilai indeks yang cocok dalam satu halaman, tetapi apakah kuncinya adalah int 4 byte (yang mungkin tidak cukup besar dan tidak dapat dihasilkan klien) atau nilai 16 byte bukanlah masalah yang signifikan. Dalam beberapa database, rowId dapat berukuran 16 byte.
ipaul
9

Ada satu masalah lagi dengan menggunakan string sebagai kunci, atau lebih tepatnya, menggunakan string literal sebagai kunci, mengesampingkan alasan kinerja / efisiensi murni. Salah ketik. Jika Anda menggunakan string literal sebagai kunci dalam kamus, Anda mengatur diri sendiri untuk kejutan yang tidak menyenangkan ketika seseorang "ReceiverId"menjadi a "RecieverId". Tetapkan konstanta untuk menyimpan nilai-nilai kunci dan menggunakannya kembali setiap kali Anda mengakses kamus.

Sepele dan jelas, bisa dikatakan, namun sejumlah contoh kode .NET yang menakjubkan di web menggunakan string literal, menyebarkan praktik yang meragukan ini. ASP.NET dengan semua Sesi, ViewState, dan QueryParams yang tersebar di basis kode sangat bersalah di sini.

scrwtp
sumber
Bukan IMHO sepele. Saya juga melihat kasus di mana ada kunci "1"dan "1 "di tabel yang sama.
pswg
Dapatkan lebih lucu ketika Anda melempar sensitivitas case dalam campuran juga. Terlihat banyak orang termasuk saya tersandung langsung ke yang itu.
Tony Hopkinson
Bahkan lebih baik daripada menggunakan konstanta, setidaknya dalam C #, menggunakan Ekspresi sebagai gantinya. Dengan cara itu Anda dapat menghasilkan string Anda dari nama metode / properti dll sehingga pencarian string Anda menjadi tipe yang aman dan ramah refactor.
GoatInTheMachine
4

Ada banyak pengorbanan di sini. Sebenarnya saya sering menggunakan kunci string, tetapi sering saya menyertakan pengganti kunci sekunder untuk bergabung (jelas itu akan menjadi sebaliknya jika saya menggunakan MySQL). Namun ada beberapa kasus di mana saya tidak melakukannya.

Pertama, saya penggemar menyatakan kunci alami sebagai kunci utama di mana db dapat menangani ini dengan baik (misalnya PostgreSQL). Ini membantu normalisasi dan membuat desain database lebih jelas. Kunci pengganti membuat bergabung lebih mudah.

Ada dua alasan mengapa saya biasanya menambahkan kunci pengganti:

  1. Tidak selalu jelas apa kunci alami itu. Terkadang ini harus diubah. Mengubah kunci komposit alami ketika digunakan untuk bergabung dan integritas referensial rumit dan rentan kesalahan.

  2. Menggabungkan kinerja pada kunci komposit bermasalah dan sekali Anda pergi ke rute kunci alami, Anda terjebak di sana.

Dalam kasus di mana kunci alami adalah definisi, kolom tunggal, dan teks, bagaimanapun, saya biasanya bergabung dengan kunci string. Alasan saya untuk melakukannya adalah bahwa ini sering menghindari bergabung saat pencarian. Penggunaan yang paling umum adalah menyediakan desain db yang tepat di sekitar kasus penggunaan jenis enum. Dalam kebanyakan kasus, ini tidak memerlukan gabung tambahan untuk permintaan rutin. Jadi di mana ini kasusnya, kunci string sebagai tombol bergabung masuk akal.

Misalnya di LedgerSMB, kami menyimpan kategorisasi akun. Ini diidentifikasi oleh referensi string. Dan beberapa data lainnya disimpan dengan referensi string yang digunakan untuk menegakkan aturan mengenai kombinasi kategorisasi yang dapat mempengaruhi akun. Satu-satunya waktu yang dibutuhkan oleh logika adalah ketika menyimpan satu set kategorisasi, jadi kami bergabung dengan kunci string.

Seperti mengapa default akan menjadi kunci integer, saya tidak berpikir itu hanya masalah ukuran indeks. Masalah besar adalah manajemen kunci. Karena kuncinya adalah arbitrer dan Anda mungkin berurusan dengan jutaan catatan, Anda harus memiliki cara untuk menghasilkan string yang unik. Ada kasus di mana orang menggunakan UUID untuk ini, tetapi ada kemungkinan tidak ada tumbukan UUID, dan di mana miliaran catatan disimpan, peluang ini menjadi cukup tinggi yang mungkin benar-benar melihat sementara peluang tabrakan dengan tipe bilangan bulat meningkat adalah nol Menurut definisi.

Chris Travers
sumber
Ini bukan nol jika Anda berhasil membuat tipe integer membungkus kembali ke nol. Untuk tipe 32-bit yang tidak ditandatangani, yang hanya berjarak 4G, yang sangat dekat dengan "milyaran catatan" ...
Donal Fellows
Jika Anda memiliki db yang dapat Anda katakan "kesalahan daripada membungkus" itu adalah nol. Bagaimanapun, lebih mudah untuk mengelola kemungkinan tabrakan dengan bilangan bulat yang meningkat daripada dengan nilai pseudorandom.
Chris Travers
1

Ada sejumlah masalah potensial dengan menggunakan string sebagai kunci, terutama ketika datang ke tabel seperti sql. Seperti yang disebutkan oleh @ kelinci, indeks untuk tabel Anda akan menjadi lebih besar, tapi saya pikir lebih signifikan, setiap hubungan kunci asing ke tabel akan melibatkan KEDUA tabel untuk mengandung string yang bertentangan dengan pengidentifikasi bobot-lebih ringan (integer) . Jika Anda menemukan bahwa ada lebih banyak tabel dengan referensi ke yang pertama, kunci string akan diperbanyak di seluruh basis data Anda.

Matthew Flynn
sumber
1

Ini bukan ide yang buruk dalam dirinya sendiri, biasanya dengan 20/20 melihat ke belakang kompromi desain yang buruk. Fleksibilitas dan jangkauan string versus biaya dan kompleksitas tambahan.

Jika integer melakukan rentang pekerjaan dengan bijak dan sebagian besar pemrosesan yang mahal tidak perlu tahu apa yang diwakili bilangan bulat, gunakan satu.

Tony Hopkinson
sumber
0

Anda entah bagaimana mengambil data yang salah dari Hashtable.

Apakah maksud Anda "DaytimeTelephone" atau "EveningTelephone"?

atau

Apakah maksud Anda 1234567 atau 1234576?

Sementara angka bisa dibilang lebih efisien untuk mesin , kapan pun keadaan serba salah (dan memang begitu), itu tergantung pada Anda dan saya untuk memahami apa yang terjadi dan, pada saat itu, penghematan beberapa byte penyimpanan dan beberapa mikro (nano?) - detik pemrosesan hilang kejelasan setiap saat.

Phill W.
sumber
1
Dan dengan demikian Anda berakhir dengan daftar konstanta, menggunakan nama konstanta dalam kode Anda untuk mewakili angka ajaib ... Java enums untuk menyelamatkan abstrak lebih jauh dan meninggalkan Anda hanya dengan nama dan memiliki ordinal pemetaan tidak terlihat.
jwenting
-1

Banyak pertukaran dan tidak ada jawaban yang benar. Banyak programmer tidak akan pernah mempertimbangkan untuk menggunakan kunci string dalam database karena mereka tidak menyadari hashing dan cara kerja database. Kunci string selama mereka sangat stabil, atau tidak berarti (pengganti), adalah pilihan desain yang baik dalam banyak keadaan.

lumut23
sumber
2
Jawaban ini tidak menambahkan apa pun yang belum dikatakan di jawaban lain, yang mengatakannya lebih baik.
Martijn Pieters
-2

kunci string akan masuk akal, ketika datang ke tabel pencarian dengan sekitar 10-100 catatan string pendek; data terkait lebih mudah dibaca + mis. pelacakan perubahan (numeric / guid id vs string mis. "Administrator"); btw, database Keanggotaan ASP.NET menggunakan kunci string untuk AspNetRoles.

hitchcock alfred
sumber