Arama Tablolarının Doğru Kullanımı


25

Bir veritabanında arama tablolarının ne zaman ve nerede kullanılacağı konusunda tam olarak nasıl sınırlar yerleştirileceğini bulmakta güçlük çekiyorum. Baktığım çoğu kaynak hiçbir zaman çok fazla olamayacağımı söylüyor, ancak bir noktada, veritabanı o kadar çok parçaya bölünmüş gibi görünüyor ki, verimli olsa da artık yönetilemez. İşte birlikte çalıştığım şeye bir atılmış örnek:

Çalışanlar adında bir masam var diyelim:

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

Bir an için verinin daha karmaşık ve yüzlerce satır içerdiğini düşünün. Arama masasına taşınabileceğini gördüğüm en bariz şey Position. Konumlar adı verilen bir tablo oluşturabilir ve Konumlar tablosundaki yabancı anahtarları Konum sütununda Çalışanlar tablosuna yapıştırabilirim.

ID  Position
1   Manager
2   Sales

Ancak, yönetilemez hale gelmeden önce bilgileri daha küçük arama tablolarına bölmeye nasıl devam edebilirim? Bir Toplumsal Cinsiyet tablosu oluşturabilir ve 1’in Erkek’e, 2’sinin de Dişi’ye ayrı bir arama tablosunda eşleşmesini sağlayabilirim. LNames ve FNames'i tablolara bile koyabilirim. Tüm "John" girişleri, 1'in kimliğinin John'a karşılık geldiğini belirten FName tablosuna işaret eden 1 yabancı anahtarla değiştirilir. Bu tavşan deliğinden bu kadar aşağı inerseniz, Çalışanlar masanız yabancı anahtar karmaşasına indirgenir:

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

Bu, bir sunucunun işlemesi için daha verimli olabilir veya olmayabilir, ancak bu kesinlikle onu korumayı deneyen ve uygulama geliştiricisinin erişmeye çalıştığı bir uygulama geliştiricisi için zorlaştıran normal bir kişi tarafından okunamaz. Öyleyse benim asıl sorum ne kadar uzakta? Bu tür bir şey için "en iyi uygulamalar" var mı yoksa bir yerlerde iyi bir kurallar dizisi var mı? Sahip olduğum bu konu için gerçekten iyi ve kullanışlı bir kılavuzlar dizini çağıran hiçbir bilgiyi çevrimiçi bulamıyorum. Veritabanı tasarımı benim için eski bir şapka ama İYİ veritabanı tasarımı çok yeni, bu yüzden aşırı teknik cevaplar kafamda olabilir. Herhangi bir yardım takdir edilecektir!


5
"Arama" tablolarını kullanmak bir şeydir. Metni kimlik numaralarıyla değiştirmek tamamen farklı bir şeydir.
Mike Sherrill 'Cat Recall'

1
Cinsiyet her zaman 2 değere sabitlenemez! Artık cinsiyet geçişlerine sahip olduğumuz için, bir başvuruda “şimdi erkek doğumlu” veya “şimdi erkek doğumlu” gibi ek kategorilere ihtiyaç duymayabilir.

@Mike, iyi yorum!
Walter Mitty

Mağazamda, düşünürler sadece dört seçeneğin ardından durabiliyorlardı, erkek, kadın, transseksüel, ifşa edemezdi.
kevinsky

Yanıtlar:


22

Ancak, yönetilemez hale gelmeden önce bilgileri daha küçük arama tablolarına bölmeye nasıl devam edebilirim? Bir Toplumsal Cinsiyet tablosu oluşturabilir ve 1’in Erkek’e, 2’sinin de Dişi’ye ayrı bir arama tablosunda eşleşmesini sağlayabilirim.

İki farklı konuyu karıştırıyorsun. Bir sorun bir "arama" tablonun kullanılmasıdır; diğeri ise vekil tuşların kullanılmasıdır (kimlik numaraları).

Bu tablodan başla.

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

Bu gibi pozisyonlar için bir "arama" tablosu oluşturabilirsiniz.

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);

Orijinal tablonuz tam olarak "arama" tablosu oluşturmadan önce olduğu gibi görünüyor. Ve çalışanların masa gerektiren hiçbir ek bunun dışında kullanışlı, insanlar tarafından okunabilir veri almak için katılır.

Bir "arama" tablosu kullanmak aşağıdakilere dayanıyor: Uygulamanızın bir yabancı anahtar referansının sağladığı giriş değerleri üzerindeki kontrole ihtiyacı var mı? Öyleyse, her zaman bir "arama" tablosu kullanabilirsiniz. (Bir yedek anahtar kullanıp kullanmadığına bakılmaksızın)

Bazı durumlarda, bu masayı tasarım zamanında tamamen doldurabilirsiniz. Diğer durumlarda, kullanıcıların çalışma zamanında bu tabloya satır ekleyebilmeleri gerekir. (Ve muhtemelen yeni verileri incelemek için bazı idari süreçler eklemeniz gerekecek.) Gerçekten de ISO standardı olan cinsiyet tasarım zamanında tamamen doldurulabilir. Uluslararası çevrimiçi ürün siparişlerinin sokak adları muhtemelen çalışma zamanında eklenmelidir.


2
Bunları yapabileceğini bilmiyordum! Metodunun çalışma şekli çok güzel. Teşekkür ederim!
Brad Turner

4
DBA Stack Exchange'e katıldım, böylece bu cevabı oylayabiliyorum. Bu güzel ve başıma hiç gelmedi. Teşekkürler!
CindyH,

Arama tablosunu doldurma yöntemini takdir ediyorum. Bu soruyu okumak için benim neden arama tablolarımdaki bir vekil anahtarın göremediğim bir yarar olup olmadığını görmek oldu. Benim için tek bir metin alanının göründüğü kadar iyi ve kullanışlı olduğunu onayladınız. Teşekkür ederim.
Sinthia V

8

Çalışanlar tablonuzda, yalnızca "Konum" konusunu araştıracağım çünkü genişleyebilecek sınırlı bir veri kümesi.

  • Cinsiyet kendi kendini tarif eder (söyler Mveya söyler F), 2 değerle sınırlıdır ve bir CHECK kısıtlaması ile uygulanabilir. Yeni Cinsiyetler ekleyemezsiniz (siyasi doğruluk bollock'larını göz ardı ederek)
  • İlk adı "John" sınırlı, kısıtlı veri kümesinin bir parçası değildir: Potansiyel veri kümesi etkin bir şekilde sınırsız noktaya kadar büyüktür, bu yüzden bir arama olmamalıdır

Yeni bir Konum eklemek istiyorsanız, arama tablosuna bir satır eklemeniz yeterlidir. Bu , normalizasyonun bir noktası olan veri modifikasyon anomalilerini de ortadan kaldırır .

Ayrıca, bir milyon çalışanınız olduğunda o zaman tinyint PositionID'i depolamak varchar'dan daha verimlidir.

Yeni bir sütun "maaş para birimi" ekleyelim. Burada CHF, GBP, EUR, USD gibi bir anahtarla arama tablosu kullanırdım: Bir anahtar kullanmazdım. Bu, Cinsiyet gibi bir CHECK kısıtlamasıyla sınırlandırılabilir, ancak Position gibi sınırlı ama genişletilebilir bir veri kümesidir. Bu örneği verdim çünkü doğal anahtarı, milyonlarca çalışan verisinde görünse bile, küçücükten ziyade char (3) olmasına rağmen kullanıyorum.

Yani, özetlemek için arama tablolarını kullanıyorsunuz.

  1. Bir sütunda sonlu ancak genişletilebilir bir küme verisine sahipseniz
  2. kendini tarif etme nerede
  3. veri değişikliği anormalliklerini önlemek için

1
Cinsiyeti arama masasına yerleştirmenin olası bir nedeni yerelleştirmedir.
a_horse_with_no_name

1
"Cinsiyet ... (M veya F diyelim), 2 değerle sınırlandırılmış ... siyasi doğruluk bollock'larını göz ardı ederek" - İronik olarak, insanların yanlış bir şekilde "cinsiyet" e gitmelerine neden olan, görünüşte aynı siyasi doğruluktur (' Eril ',' Kadınsı ') "seks" derken (' Erkek ',' Kadın '). Bağlam dilbilgisi cinsiyse, genellikle ikiden fazla değer vardır. Bağlam yenidoğanın cinsiyetini kaydediyorsa en az dört değer vardır ('resmi olarak değerlendirilmedi' ve 'resmi değerlendirme sonuçsuzdu'). ps sert
görünmek istemiyorum

4
@ onedaywhen: "Sex" adlı bir sütunun doğru değeri "Evet, lütfen" dir. İngiliz
gbn

Terim normalleşme ile ilgili farklı bir özel anlama sahip olduğu ve bağlantı uygun olmadığı için burada "anomiller" terimi kötüye kullanılmaktadır.
philipxy

5

Cevap bir "bağlıdır" dır. Çok tatmin edici değil ama tasarımı zorlayan ve çeken pek çok etki var. Veritabanını tasarlayan uygulama programcılarınız varsa, tanımladığınız gibi bir yapı ORM'nin karmaşıklığını gizlediği için onlar için çalışır. Rapor yazarken saçınızı çekip, bir adres almak için on masaya katılmak zorunda kalacaksınız.

Kullanım, amaçlanan kullanım ve gelecekteki kullanım için tasarım. İş süreci hakkındaki bilginizin geldiği yer burasıdır. Bir veterinerlik işletmesi için bir veritabanı tasarlıyorsanız, yüksek teknolojili bir işletmeden oldukça farklı olacak olan işlevsellikteki boyut, kullanım ve talimatlar hakkında makul varsayımlar vardır.

Favori bir teklifi yeniden kullanmak için

"Bilge bir adam bir keresinde bana" canı yanana kadar normalleş, çalışana kadar denormalize et "dedi.

İçinde bir yerlerde tatlı nokta var. Tecrübelerime göre, bir anahtar kimliğini birden fazla masada bulundurmak, bazı birincil anahtarları değiştirmemeniz durumunda, sandığınız kadar ciddi bir suç değildir.

Bu normalize edilmiş tabloların kısaltılmış örneğini gerçek bir sistemden alın

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);

Bu tablolar, tek özelliklerin ve üst alt özelliklerin bağlantılı bir listesini oluşturur ve burada kullanılırlar.

  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);

Bu iyi görünüyor: tek bir seçimde property_id özellikli tüm davaları alın

Almak için bir liste alalım

 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

Şimdi, 3 ve 4 ve 5 özellik özelliklerine sahipse ya da değilse, bir vakanın tüm özelliklerini seçmeyi deneyin.

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  

Bu sadece ... bununla başa çıkmanın daha şık yollarını kullandığında bile canımı yakıyor. Ancak, bir davanın yalnızca bir property_id değerine sahip olacağı özellikleri ayırarak normalizasyonu biraz ekleyin ve bu daha iyi olabilir.

Ne zaman çok fazla tablonuz olduğunu veya yeterli olmadığını öğrenmek için veritabanını sorgulamayı denediğinizde soruyu soracağınız uygulamayı, bir raporu ve yıldan yıla analizleri kullanmalısınız.


5
Kimlik numaralarının normalleştirme ile ilgisi yoktur. Sırf her tablonun bir kimlik numarası olması 5NF, hatta 3NF olması anlamına gelmez. Bu sadece bu tablodan kullanılabilir verileri almak için çok fazla katılım yapmanız gerektiği anlamına gelir .
Mike Sherrill 'Cat Recall'
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.