Biri hariç tüm sütunları birincil anahtar olarak işaretlemek makul mü?


9

Filmleri temsil eden bir masam var. Alanlar:
id (PK), title, genre, runtime, released_in, tags, origin, downloads.

Veritabanım yinelenen satırlar tarafından kirletilemez, bu yüzden benzersizliği zorlamak istiyorum. Sorun farklı film aynı başlığa sahip olabilir, hatta aynı alanlar hariç olmasıdır tagsve downloads. Benzersizliği nasıl zorlayabilirim?

İki şekilde düşündüm:

  • downloadsbirincil anahtar hariç tüm alanları oluşturur . Ben tutuyorum downloads's JSON bu yana ve muhtemelen performansını etkileyecektir.
  • yalnızca idbirincil anahtar olarak saklayın , ancak diğer tüm sütunlara (yine hariç downloads) benzersiz bir kısıtlama ekleyin .

Çok benzer olan bu soruyu okudum , ama ne yapmam gerektiğini tam olarak anlamadım. Şu anda bu tablo diğer tablolarla ilgili değildir, ancak gelecekte olabilir.

Şu anda 20.000'den az kayıtım var, ancak sayının artmasını bekliyorum. Bunun konuyla biraz alakalı olup olmadığını bilmiyorum.

DÜZENLEME: Şemayı değiştirdim ve işte tabloyu nasıl oluşturacağım:

CREATE TABLE movies (
    id          serial PRIMARY KEY,
    title       text NOT NULL,
    runtime     smallint NOT NULL CHECK (runtime >= 0),
    released_in smallint NOT NULL CHECK (released_in > 0),
    genres      text[] NOT NULL default ARRAY[]::text[],
    tags        text[] NOT NULL default ARRAY[]::text[],
    origin      text[] NOT NULL default ARRAY[]::text[],
    downloads   json NOT NULL,
    inserted_at timestamp NOT NULL default current_timestamp,
    CONSTRAINT must_be_unique UNIQUE(title,runtime,released_in,genres,tags,origin)
);

timestampSütunu da ekledim , ancak dokunmayacağım için bu bir sorun değil. Bu yüzden her zaman otomatik ve benzersiz olacaktır.


SO ile yakından ilgili soru (cevap ile) SO: Biri NULL olabilir bir BENZERSİZ (bileşik 4 sütun) olan benim tablo için birincil bir anahtar gerekir mi? . Sütunlardan herhangi biri NULL olursa, acilen şunu düşünün: dba.stackexchange.com/q/9759/3684 .
Erwin Brandstetter

Yanıtlar:


4

Tablo tanımınız artık makul görünüyor. Tüm sütunların ile yazım hataları ve korkarım doğrusu ortak olabilir imla ufak farklılıklar dışında - kısıt beklendiği gibi çalışır. @ A_horse adlı kullanıcının yorumunu düşünün .NOT NULLUNIQUE

Fonksiyonel benzersiz indeks ile alternatif

Diğer seçenek işlevsel bir benzersiz dizin ( @Dave'in yorumuna benzer ) olacaktır. Ancak uuiddizin boyutunu ve performansını optimize etmek için bir veri türü kullanırdım.

Diziden metne IMMUTABLEaktarım işlemi (genel uygulaması nedeniyle):

Bu nedenle değişmez olduğunu ilan etmek için küçük bir yardımcı fonksiyona ihtiyacınız var :

CREATE OR REPLACE FUNCTION f_movie_uuid(_title text
                                      , _runtime int2
                                      , _released_in int2
                                      , _genres text[]
                                      , _tags text[]
                                      , _origin text[])
  RETURNS uuid LANGUAGE sql IMMUTABLE AS  -- faking IMMUTABLE
'SELECT md5(_title || _runtime::text || _released_in::text
         || _genres::text || _tags::text || _origin::text)::uuid';

Dizin tanımı için kullanın:

CREATE UNIQUE INDEX movies_uni_idx
ON movies (f_movie_uuid(title,runtime,released_in,genres,tags,origin));

SQL Fiddle.

Daha fazla detay:

Oluşturulan UUID'yi PK olarak kullanabilirsiniz, ancak yine de serialFK referansları ve diğer amaçlar için basit ve ucuz olan 4 baytlı sütunu kullanırım . Bir UUID, bağımsız olarak PK değerleri üretmesi gereken dağıtılmış sistemler için mükemmel bir seçenek olacaktır. Ya da çok büyük masalar için, ama güneş sistemimizde bunun için yeterince film yok.

Lehte ve aleyhte olanlar

Bir benzersiz kısıtlama dahil sütunlarda benzersiz bir dizin uygulanmaktadır. İlk önce ilgili sütunları kısıt tanımına koyun ve teminat yararı olarak başka amaçlar için yararlı bir dizininiz var.

Başka özel avantajlar da var, bir liste:

Fonksiyonel benzersiz dizin ölçüde daha hızlı yapabilirsiniz, hangi boyut olarak daha küçük (potansiyel olarak çok) 'dir. Sütunlarınız çok büyük değilse, fark çok fazla olmaz. Hesaplama için küçük genel masraf da vardır.

Tüm sütunları bitiştirme yanlış pozitif (tanıtabilirsiniz 'foo ' || 'bar' = 'foob ' || 'ar'ama görünüyor çok bu durum için olası. Yazım hataları çok daha muhtemel güvenli bir şekilde burada yok sayabilirsiniz yönünde.

Benzersizlik ve diziler

Diziler , operatöre dayalı herhangi bir benzersiz düzenlemede anlamlı olması için tutarlı bir şekilde sıralanmalıdır . Ben çizelgeler önermek , ve ile dizi öğeleri için bulanık arama yapmalarını sağlamak PK ve benzersiz girişleri,. Sonra:='{1,2}' <> '{2,1}'genretagoriginserial

Her iki şekilde de, doğrudan dizilerle veya normalleştirilmiş bir şema ve materyalize görünümle çalışmak, arama doğru dizin ve işleçlerle çok verimli olabilir:

bir kenara

Postgres 9.4 veya üstünü kullanıyorsanız jsonbyerinejson düşünün .


6

Bir grup arkadaşınızla dışarıda olduğunuzu ve sohbetin filmlere dönüştüğünü hayal edin. Birisi "Üç Silahşör" hakkında ne düşünüyorsun? " "Hangisi?"

Aynı filmi düşündüğünüzden kesinlikle emin olmak için hangi ek bilgilere ihtiyacınız var? Yönetmenin adı? Prodüksiyon stüdyosu mu? Çıkış yılı mı? Yıldızın isimlerinden biri mi? İki veya daha fazlasının bir kombinasyonu?

Sorumun cevabı ve seninki aynı.

Ancak, türün iyi bir aday olacağını düşünmüyorum . Bir sebep, tür çok öznel bir kriterdir. 'Üç Silahşör' eylemi midir? dram? macera? komedi? Aksiyon macera? romantik Komedi? Aynı filmi farklı türler altında listeliyorum. Birden çok türe izin verdiğinizde bile, kullanıcınız aradıkları gerçek filmde listelenmeyen tamamen farklı bir tane seçebilir.

Çalışma zamanları bile, özellikle tiyatro ve VCR / DVD / b-ray sürümleri arasında farklılık gösterebilir.

Dolayısıyla, bir medya yayınından diğerine değişmeyecek zor, nesnel niteliklere ihtiyacınız var. Ne yazık ki, özellikle bir devam filmi yayınlandıktan sonra filmlerin yeniden adlandırıldığı bilindiği için filmin adını hariç tutabilir.

Çıkış tarihi ne olacak? 1993 tiyatrosu mu? 1999 VCR sürümü? 2004'ün DVD sürümü mü? Kaptın bu işi.

Düşünmeye gel, Alan Smithee'nin yönettiği bu filmlerden ne haber? Gerçek yönetmen nihayet gerçekliğin ardından projeye adını koymak için ileri adım attı mı? Bilmiyorum.

Hmm, hala bazı kriterler kalırken dursam iyi olur.

Bazı ek noktalar:

  • Evet, vekil anahtarı saklayın ve doğal anahtar alanlarında benzersiz bir dizin oluşturun (eğer nihayetinde çivilenebilirseniz). Yedek anahtar, yabancı anahtar referansları için en iyisidir. Bir filme referans içeren her tablodaki tüm doğal anahtar alanlarını çoğaltmak istemezsiniz.
  • Dizi alanlarını (türler, etiketler, kökenler) bırakın. Devam edin ve bu nitelikleri uygun şekilde normalleştirin. Ben özellikle onları aranabilir olmak istiyorsanız ("... nerede tür = 'korku' ..."), değerinden daha fazla sorun değil bir dizi alan hiç görmedim. Bu Not değil - otomatik ( "bilim-kurgu," vs "Bilim Kurgu") vaka farklılıkları ve yazım ile ilgili sorunlar ortadan düzgün arama tabloları korumak sürece . Ancak, küçük bir tablonun bir alanındaki bu tür farklılıkları kontrol etmek, büyük bir tablonun her satırındaki her dizi hücresinden çok daha kolaydır.

4

Zorlamak istediğiniz / gereksinim duyduğunuz benzersizlik söz konusu olduğunda kimlik sütununun hiçbir avantajı yoktur. Niteliklerin herhangi bir kombinasyonunun benzersizliği hiçbir zaman anlamsız bir kimlik eklenerek uygulanmayacaktır. "Avantajı", yalnızca bunun için yabancı anahtar gerektiren yeni bir masaya ihtiyaç duyduğunuz noktaya geldiğinizde gösterilir. Bu durumda ve Kimliği eklediyseniz, bunu yeni tablonuzda FK olarak kullanabilirsiniz. (Ama bunun ücretsiz bir öğle yemeği olacağını düşünmeyin. Böyle bir yaklaşımın dezavantajı, kendinizi sadece yaptığınız yeni tablonun bir parçası olabilecek bilgileri getirmek için daha fazla birleşim yazarken bulacaksınız. )


1
İş kuralları, FOO ve BAR özelliklerindeki değer kombinasyonunun benzersiz olması gerektiğini söylüyorsa, bir kimlik eklemek bunu başaramaz. Kimliğin eklenmesi referans tablolarına FOO ve BAR eklemekten kaçınmayı kolaylaştırır. Bu da FOO ve BAR niteliklerinin (BUSINESS tanımlayıcılarını taşıyan) olabilecekleri yerde (ve en azından bir işletme açısından olması muhtemel olduğu tahmin edilen) olmadığı için daha fazla birleştirme gerektirir.
Erwin Smout

1
Benzersiz olması gereken "satırlar" DEĞİLDİR, işletmenin söyledikleri, olması gereken tanımlayıcılarıdır. Bu, FOO ve BAR özelliklerinin bir kombinasyonuysa, o zaman FOO ve BAR özelliklerinin birleşimidir.
Erwin Smout

2
Id olması veya olmaması, tablonuzdaki "işletme" sütunlarının benzersizliğinin uygulanmasına ilişkin herhangi bir sorunu çözmez. Benzersizliğin uygulanması, uygun anahtarları bildirerek yapılmalıdır (bunu yaparsınız - "ANAHTAR" yerine sözdizimsel "CONSTRAINT" kelimesini kullanmanız, anahtar olmadığı anlamına gelmez).
Erwin Smout
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.