Penggunaan Tabel Pencarian yang Benar


25

Saya mengalami kesulitan mencari tahu bagaimana cara menempatkan batas yang baik untuk kapan dan di mana menggunakan tabel pencarian dalam database. Sebagian besar sumber yang pernah saya lihat mengatakan bahwa saya tidak akan pernah memiliki terlalu banyak tetapi, pada titik tertentu, sepertinya basis data akan dipecah menjadi banyak bagian sehingga, walaupun mungkin efisien, ia tidak lagi dapat dikelola. Berikut adalah contoh bersama tentang apa yang saya kerjakan:

Katakanlah saya memiliki meja yang disebut Karyawan:

ID  LName   FName   Gender  Position
1   Doe     John    Male    Manager
2   Doe     Jane    Female  Sales
3   Smith   John    Male    Sales

Berpura-puralah sejenak bahwa datanya lebih kompleks dan berisi ratusan baris. Hal yang paling jelas saya lihat yang bisa dipindahkan ke tabel pencarian adalah Posisi. Saya bisa membuat tabel yang disebut Posisi dan menempelkan kunci asing dari tabel Posisi ke dalam tabel Karyawan di kolom Posisi.

ID  Position
1   Manager
2   Sales

Tapi seberapa jauh saya bisa terus memecah informasi menjadi tabel pencarian yang lebih kecil sebelum menjadi tidak terkelola? Saya bisa membuat tabel Jenis Kelamin dan memiliki 1 korespondensi untuk Pria dan 2 korespondensi dengan Perempuan dalam tabel pencarian terpisah. Saya bahkan bisa memasukkan LNames dan FNames ke dalam tabel. Semua entri "John" diganti dengan kunci asing 1 yang menunjuk ke tabel FName yang mengatakan ID 1 sesuai dengan John. Jika Anda turun ke lubang kelinci ini terlalu jauh seperti ini, meja Karyawan Anda kemudian dikurangi menjadi berantakan kunci asing:

ID  LName   FName   Gender  Position
1   1       1       1       1
2   1       2       2       2
3   2       1       1       2

Walaupun ini mungkin atau mungkin tidak lebih efisien untuk diproses oleh server, ini tentu tidak dapat dibaca oleh orang normal yang mungkin mencoba untuk mempertahankannya dan membuatnya lebih sulit bagi pengembang aplikasi yang mencoba mengaksesnya. Jadi, pertanyaan saya yang sebenarnya adalah seberapa jauh terlalu jauh? Apakah ada "praktik terbaik" untuk hal semacam ini atau seperangkat pedoman yang baik di suatu tempat? Saya tidak dapat menemukan informasi online apa pun yang benar-benar menetapkan serangkaian pedoman yang baik dan dapat digunakan untuk masalah khusus yang saya alami ini. Desain basis data adalah topi lama bagi saya tetapi desain basis data yang bagus sangat baru sehingga jawaban teknis yang terlalu banyak mungkin ada di kepala saya. Bantuan apa pun akan dihargai!


5
Menggunakan tabel "pencarian" adalah satu hal. Mengganti teks dengan nomor id adalah hal yang sama sekali berbeda.
Mike Sherrill 'Cat Recall'

1
Jenis kelamin tidak selalu dapat diperbaiki menjadi 2 nilai! Sekarang kita memiliki transisi gender, yang mengatakan aplikasi mungkin tidak memerlukan kategori tambahan seperti 'lahir laki-laki sekarang perempuan' atau 'perempuan lahir sekarang laki-laki'.

@ Mike, komentar yang bagus!
Walter Mitty

Di toko saya, para pemikir dapat berhenti setelah hanya empat pilihan, pria, wanita, waria, tidak mau mengungkapkan.
kevinsky

Jawaban:


22

Tapi seberapa jauh saya bisa terus memecah informasi menjadi tabel pencarian yang lebih kecil sebelum menjadi tidak terkelola? Saya bisa membuat tabel Jenis Kelamin dan memiliki 1 korespondensi untuk Pria dan 2 koresponden untuk Perempuan di tabel pencarian terpisah.

Anda mencampur dua masalah berbeda. Salah satu masalah adalah penggunaan tabel "pencarian"; yang lainnya adalah penggunaan kunci pengganti (nomor id).

Mulai dengan tabel ini.

ID  LName   FName   Gender  Position
1   Doe     John    Male    Manager
2   Doe     Jane    Female  Sales
3   Smith   John    Male    Sales

Anda dapat membuat tabel "pencarian" untuk posisi seperti ini.

create table positions (
  pos_name varchar(10) primary key
);

insert into positions
select distinct position 
from employees;

alter table employees
add constraint emp_fk1
foreign key (position) 
  references positions (pos_name);

Tabel asli Anda terlihat persis seperti sebelum membuat tabel "pencarian". Dan tabel karyawan tidak memerlukan tambahan bergabung untuk mendapatkan data yang bermanfaat dan dapat dibaca oleh manusia.

Menggunakan tabel "pencarian" bermuara di bawah ini: Apakah aplikasi Anda memerlukan kontrol atas nilai input yang disediakan oleh referensi kunci asing? Jika demikian, maka Anda selalu dapat menggunakan tabel "pencarian". (Terlepas dari apakah itu menggunakan kunci pengganti.)

Dalam beberapa kasus, Anda dapat mengisi tabel tersebut sepenuhnya pada waktu desain. Dalam kasus lain, pengguna harus dapat menambahkan baris ke tabel itu pada saat run time. (Dan Anda mungkin perlu memasukkan beberapa proses administrasi untuk meninjau data baru.) Jenis kelamin, yang sebenarnya memiliki standar ISO , dapat sepenuhnya diisi pada waktu desain. Nama jalan untuk pesanan produk online internasional mungkin harus ditambahkan pada waktu berjalan.


2
Saya tidak tahu Anda bisa melakukan semua itu! Cara metode Anda bekerja agak indah. Terima kasih!
Brad Turner

4
Saya bergabung dengan DBA Stack Exchange supaya saya dapat memilih jawaban ini. Ini indah dan tidak pernah terpikir oleh saya. Terima kasih!
CindyH

Saya menghargai metode untuk mengisi tabel pencarian. Alasan saya membaca pertanyaan ini adalah untuk melihat apakah ada manfaat yang tidak bisa saya lihat pada kunci pengganti di tabel pencarian saya. Anda mengonfirmasi bagi saya satu bidang teks sama bagus dan bermanfaatnya seperti yang ditampilkan. Terima kasih.
Sinthia V

8

Di tabel Karyawan Anda, saya hanya akan mencari "Posisi" karena ini adalah kumpulan data terbatas yang dapat diperluas.

  • Jender menggambarkan diri sendiri (katakan Matau F), terbatas pada 2 nilai, dan dapat ditegakkan dengan kendala PERIKSA. Anda tidak akan menambahkan jenis kelamin baru (mengabaikan bollocks kebenaran politik)
  • Nama pertama "John" bukan bagian dari kumpulan data yang terbatas dan terbatas: kumpulan data yang potensial sangat besar hingga secara efektif tidak terbatas sehingga tidak boleh menjadi pencarian.

Jika Anda ingin menambahkan Posisi baru Anda cukup menambahkan baris ke tabel pencarian. Ini juga menghilangkan anomali modifikasi data yang merupakan salah satu titik normalisasi

Juga, begitu Anda memiliki sejuta karyawan, maka lebih efisien untuk menyimpan Positionint mungintip daripada varchar.

Mari tambahkan kolom baru "mata uang gaji". Saya akan menggunakan tabel pencarian di sini dengan kunci CHF, GBP, EUR, USD dll: Saya tidak akan menggunakan kunci pengganti. Ini dapat dibatasi dengan batasan PERIKSA seperti Jenis Kelamin, tetapi ini adalah set data yang terbatas namun dapat diperluas seperti Posisi. Saya memberikan contoh ini karena saya akan menggunakan kunci alami bahkan jika itu muncul dalam sejuta baris data karyawan meskipun char (3) daripada tinyint

Jadi, untuk meringkas, Anda menggunakan tabel pencarian

  1. di mana Anda memiliki kumpulan data yang terbatas, namun dapat diperluas dalam sebuah kolom
  2. di mana tidak menggambarkan diri
  3. untuk menghindari anomali modifikasi data

1
Salah satu alasan yang memungkinkan untuk menempatkan gender ke dalam tabel pencarian adalah lokalisasi.
a_horse_with_no_name

1
"Jenis kelamin ... (katakanlah M atau F), terbatas pada 2 nilai ... mengabaikan bollocks kebenaran politik" - Ironisnya, itu adalah kebenaran politik yang sama yang tampaknya Anda benci yang menyebabkan orang salah "gender" (' Maskulin ',' Feminin ') ketika mereka berarti "seks" (' Pria ',' Wanita '). Jika konteksnya adalah gender gramatikal maka biasanya ada lebih dari dua nilai. Jika konteksnya mencatat jenis kelamin bayi yang baru lahir maka setidaknya ada empat nilai ('belum dinilai secara resmi' dan 'penilaian resmi tidak meyakinkan'). ps Saya tidak bermaksud terdengar kasar, saya menikmati ironi :)
onedaywhen

4
@onedaywhen: nilai yang benar untuk kolom yang disebut "Seks" adalah "Ya, tolong". Kecuali Anda orang Inggris
gbn

Istilah "anomali" disalahgunakan di sini karena istilah tersebut memiliki makna khusus yang berbeda terkait dengan normalisasi, dan tautannya tidak sesuai.
philipxy

5

Jawabannya adalah "itu tergantung". Tidak terlalu memuaskan tetapi ada banyak pengaruh mendorong dan menarik desain. Jika Anda memiliki pemrogram aplikasi yang mendesain database, struktur seperti yang Anda gambarkan berfungsi untuk mereka karena ORM menyembunyikan kerumitannya. Anda akan mencabut rambut Anda ketika Anda menulis laporan dan harus bergabung dengan sepuluh tabel untuk mendapatkan alamat.

Desain untuk penggunaan, penggunaan yang dimaksudkan, dan kemungkinan penggunaan di masa depan. Di sinilah pengetahuan Anda tentang proses bisnis masuk. Jika Anda merancang database untuk bisnis veteriner, ada asumsi yang masuk akal tentang ukuran, penggunaan, dan arah fungsionalitas yang akan sangat berbeda dari permulaan teknologi tinggi.

Untuk menggunakan kembali kutipan favorit

"Orang bijak pernah mengatakan kepada saya" normalkan sampai sakit, denormalkan sampai bekerja ".

Di suatu tempat ada sweet spot. Pengalaman saya adalah bahwa memiliki id kunci di lebih dari satu tabel bukanlah kejahatan yang serius seperti yang dipikirkan beberapa orang jika Anda tidak pernah mengubah kunci primer.

Ambil contoh singkat dari tabel yang sangat dinormalisasi ini dari sistem nyata

CREATE TABLE PROPERTY
(ID                          NUMBER(9)           NOT NULL);

CREATE TABLE PROPERTY_TYPE
(ID                          NUMBER(9)           NOT NULL);

CREATE TABLE PROPERTY_LOCALE 
PROPERTY_ID                  NUMBER(9)           NOT NULL,
(LOCALE_ID                   NUMBER(9)           NOT NULL,  --language 
VALUE                        VARCHAR2(200)       NOT NULL);

CREATE TABLE PROPERTY_DEPENDENCY
(PROPERTY_ID                 NUMBER(9)           NOT NULL,
 PARENT_PROPERTY_ID          NUMBER(9)                   ,
 PROPERTY_TYPE_ID            NUMBER(9)           NOT NULL);

Tabel-tabel ini mengatur daftar properti tunggal dan properti anak induk yang ditautkan dan mereka digunakan di sini

  CREATE TABLE CASE_PROPERTY
  (ID                        NUMBER(9)           NOT NULL,
  PARENT_ID                  NUMBER(9),
  CASE_ID                    NUMBER(9)           NOT NULL,
  PROPERTY_ID                NUMBER(9),
  PROPERTY_TYPE_ID           NUMBER(9)           NOT NULL);

Ini terlihat bagus: dapatkan semua case dengan property_id dalam satu pilihan

Mari kita ambil daftar untuk dipilih

 Select pl.value, pd.property_id
 from property_locale pl, property_dependency pd
 where pl.property_id = pd.property_id
 and pd.property_type_id = 2;  --example number

Sekarang coba pilih semua properti sebuah case jika memiliki property_types 3 dan 4 dan 5, atau tidak ...

SELECT   cp2.case_id,
         (SELECT   pl.VALUE
            FROM   case_property cp, property_locale pl
           WHERE       cp.property_id = pl.property_id
                   AND CP.PROPERTY_TYPE_ID = 2
                   AND pl.locale_id = 2
                   AND cp.case_id = cp2.case_id)
            AS VALUE1,
         (SELECT   pl.VALUE
            FROM   case_property cp, property_locale pl
           WHERE       cp.property_id = pl.property_id
                   AND CP.PROPERTY_TYPE_ID = 34
                   AND pl.locale_id = 2
                   AND cp.case_id = cp2.case_id)
            AS VALUE2,
         (SELECT   pl.VALUE
            FROM   case_property cp, property_locale pl
           WHERE       cp.property_id = pl.property_id
                   AND CP.PROPERTY_TYPE_ID = 4
                   AND pl.locale_id = 2
                   AND cp.case_id = cp2.case_id)
            AS VALUE3
  FROM   case_property cp2
 WHERE   cp2.case_id = 10293  

Ini hanya menyakitkan ... bahkan ketika Anda menggunakan cara yang lebih elegan untuk menangani ini. Namun, tambahkan sedikit de normalisasi dengan memecah properti yang memiliki case hanya memiliki satu property_id dan ini bisa menjadi jauh lebih baik.

Untuk mencari tahu kapan Anda memiliki terlalu banyak tabel atau tidak cukup mencoba menanyakan database dengan pertanyaan aplikasi, laporan dan analisis tahun ke tahun akan digunakan.


5
Nomor ID tidak ada hubungannya dengan normalisasi. Hanya karena setiap tabel memiliki nomor id tidak berarti itu dalam 5NF, atau bahkan dalam 3NF. Ini hanya berarti bahwa Anda harus melakukan banyak penggabungan untuk mendapatkan data yang dapat digunakan dari tabel itu.
Mike Sherrill 'Cat Recall'
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.