INT ve VARCHAR birincil anahtarları arasında GERÇEK performans farkı var mı?


174

MySQL'de birincil anahtar olarak INT ve VARCHAR kullanımı arasında ölçülebilir bir performans farkı var mı? VARCHAR referans listeleri (ABD Devletleri, Ülke Kodları düşünüyorum) için birincil anahtar olarak kullanmak istiyorum ve bir iş arkadaşı INT AUTO_INCREMENT tüm tablolar için birincil anahtar olarak tomurcuklanmak olmaz.

Burada detaylandırılan argümanım, INT ve VARCHAR arasındaki performans farkının ihmal edilebilir olmasıdır, çünkü her INT yabancı anahtar referansı referansı anlamak için bir JOIN gerektirecektir, bir VARCHAR anahtarı doğrudan bilgiyi sunacaktır.

Peki, bu özel kullanım durumu ve bununla ilgili performans endişeleri olan herhangi biri var mı?


3
Ben çalıştığım testlerin bazı detay "hayır" cevabı ile bir yazı yaptım ... ama bu SQL Server, MySQL değil. Bu yüzden cevabımı sildim.
Timothy Khouri

17
@Timothy - Silmemeliydin. Oylama sürecindeydim. Çoğu SQL veritabanı sunucusu benzer sorgu planlayıcılarına ve benzer performans darboğazlarına sahiptir.
Paul Tomblin

9
@Timothy lütfen sonuçlarınızı tekrar gönderin.
Jake McGraw

2
Pek çok yorum ve cevap, anahtarların birleştirmeler için kullanılabileceğini varsayar. Onlar değil. Anahtarlar veri tutarlılığı için kullanılacaktır - yinelenen satırları önlemek için (aynı varlığı temsil eden birden fazla satır). Herhangi bir sütun (veya sütun kümesi) bir birleşimde kullanılabilir ve birleşmenin bire bir veya sıfır olduğunu garanti etmek için sütun [lar] ın benzersiz olması gerekir. Herhangi bir benzersiz endeks bunu garanti eder ve anlamlı olması gerekmez.
Charles Bretana

Yanıtlar:


78

Yedek anahtar yerine doğal anahtar olarak adlandırılanları kullanarak bir dizi birleştirilen sorguyu engelleyebileceğiniz iyi bir noktaya işaret edersiniz . Başvurunuzda bunun yararının önemli olup olmadığını yalnızca siz değerlendirebilirsiniz.

Yani, uygulamanızda hızlı olması için en önemli olan sorguları ölçebilirsiniz, çünkü bunlar büyük hacimli verilerle çalışır veya çok sık yürütülür. Bu sorgular bir birleştirmeyi ortadan kaldırırsa ve bir varchar birincil anahtarı kullanarak acı çekmiyorsa, bunu yapın.

Her iki stratejiyi de veritabanınızdaki tüm tablolar için kullanmayın. Bazı durumlarda doğal bir anahtarın daha iyi olması muhtemeldir, ancak diğer durumlarda bir yedek anahtar daha iyidir.

Diğer insanlar, doğal bir anahtarın asla değişmemesi veya kopyaları olmamasının pratikte nadir olduğunu iyi bir noktaya işaret ederler, bu nedenle yedek anahtarlar genellikle faydalıdır.


3
Ve bazen, (imho, çoğu zaman), her ikisi de daha iyidir, diğer tablolardaki FK referansları ve Birleşimler için kullanılacak vekil ve veri tutarlılığını sağlamak için doğal anahtar
Charles Bretana

@CharlesBretana Bu ilginç. FK'nin kenarı boyunca veri tutarlılığı için doğal bir anahtar kullanmak yaygın bir uygulama mıdır? İlk düşüncem, büyük masalarda ihtiyaç duyulacak ekstra depolama alanının değerli olamayacağıydı. Herhangi bir bilgi takdir. FYI - İyi bir programlama geçmişim var ama SQL deneyimim çoğunlukla SEÇ sorguları ile sınırlı
Rob

2
@CharlesBretana "İkisini de depola" yı okuduğumda, "artıklık" ve "normalleştirilmemiş" diye düşünüyorum. Artıklığınız varsa, çok iyi bir neden olmalıdır (tamamen kabul edilemez performans gibi) çünkü artıklık verilerinizin tutarsız olması için her zaman potansiyeldir.
jpmc26

3
@ jpmc26, Kesinlikle HİÇBİR Artıklık veya normalizasyon konusu yoktur. Bir yedek anahtarın doğal bir anahtardaki değerlerle anlamlı bir bağlantısı yoktur, bu nedenle değiştirilmemesi gerekir. Normalleştirme ile ilgili olarak, hangi normalleştirme sorunlarından bahsediyorsunuz? Normalleştirme bir ilişkinin anlamlı nitelikleri için geçerlidir; bir vekil anahtarın sayısal değeri, (aslında, vekil anahtarın kendisi kavramı) herhangi bir normalizasyon bağlamının tamamen dışındadır.
Charles Bretana

1
Ve diğer sorunuza, özellikle de bir tabloya ilişkin olarak, bu tabloda bir yedek anahtarınız varsa, örneğin frpom 1 ila 50'ye sahipseniz, ancak eyalet posta koduna başka bir benzersiz dizin veya anahtar koymuyorsanız, (ve bence, eyalet adına da), o zaman birisinin farklı yedek anahtar değerlerine sahip ancak aynı posta koduna ve / veya eyalet adına sahip iki satıra girmesini ne engeller? 'NJ', 'New Jersey' ile iki satır olsaydı, istemci uygulaması bunu nasıl hallederdi? Doğal Anahtarlar veri tutarlılığını sağlar!
Charles Bretana

81

Performansla ilgili değil. Birincil anahtarı iyi yapan şeyle ilgilidir. Zaman içinde benzersiz ve değişmez. Ülke kodu gibi bir varlığın zaman içinde asla değişmediğini ve birincil anahtar için iyi bir aday olacağını düşünebilirsiniz. Ama acı bir deneyim nadiren öyle.

INT AUTO_INCREMENT "zaman içinde benzersiz ve değişmeyen" koşulunu karşılar. Dolayısıyla tercih.


25
Doğru. En büyük veritabanlarımdan birinin Yugoslavya ve Sovyetler Birliği'ne girişi var. Birincil anahtar olmadıkları için memnunum.
Paul Tomblin

8
@Steve, ANSI SQL neden ON UPDATE CASCADE sözdizimini destekliyor?
Bill Karwin

5
Değişmezlik bir anahtarın gereği değildir. Her durumda, vekil anahtarlar bazen de değişir. İhtiyacınız olursa tuşları değiştirmekle ilgili yanlış bir şey yok.
nvogel

9
Paul, yani veritabanında Sovyetler Birliği'ni Rusya olarak mı değiştirdin? Ve SU'nun asla varolmadığını mı düşünüyorsun? Ve SU'ya yapılan tüm atıflar şimdi Rusya'yı mı gösteriyor?
Dainius

6
@ alga Ben SU'da doğdum, bu yüzden ne olduğunu biliyorum.
Dainius

52

Bu çevrimiçi için kıstasların olmaması beni biraz rahatsız etti, bu yüzden kendimi bir test yaptım.

Düzenli bir temelde yapmadığımı unutmayın, bu yüzden lütfen sonuçları istemeden etkileyebilecek herhangi bir faktör için kurulumumu ve adımlarımı kontrol edin ve endişelerinizi yorumlarda yayınlayın.

Kurulum aşağıdaki gibidir:

  • Intel® Core ™ i7-7500U CPU @ 2,70GHz × 4
  • Test sırasında 8 GB civarında temin ettiğim 15.6 GiB RAM boştu.
  • Bol miktarda boş alana sahip 148,6 GB SSD sürücü.
  • Ubuntu 16.04 64 bit
  • MySQL Ver 14.14 Linux için 5.7.20 Dağıtımı (x86_64)

Masalar:

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;

Sonra, özü şöyle bir PHP betiği ile her tabloda 10 milyon satır doldurdum:

$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.';
}

İçin intmasalar, biraz ($keys[rand(0, 9)])sadece ile değiştirildi rand(0, 9)ve için varcharmasalar, ben kesme veya 6 karakter onları uzatmadan, tam ABD devlet isimleri kullanılır. generate_random_string()10 karakterli rastgele bir dize oluşturur.

Sonra MySQL'de koştum:

  • SET SESSION query_cache_type=0;
  • İçin jan_intmasanın:
    • SELECT count(*) FROM jan_int WHERE myindex = 5;
    • SELECT BENCHMARK(1000000000, (SELECT count(*) FROM jan_int WHERE myindex = 5));
  • Yukarıdaki ile aynı diğer tablolar, için myindex = 'califo'için chartablolar ve myindex = 'california'için varchartablo.

BENCHMARKHer bir tablodaki sorgunun saatleri :

  • jan_int: 21.30 saniye
  • jan_int_index: 18.79 saniye
  • Jan_char: 21.70 saniye
  • jan_char_index: 18.85 saniye
  • jan_varchar: 21.76 saniye
  • jan_varchar_index: 18.86 saniye

Tablo ve dizin boyutlarıyla ilgili olarak, çıktısı show table status from janperformancetest;(gösterilmeyen birkaç sütunla):

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

Sonuç olarak, bu özel kullanım durumu için performans farkı yoktur.


Şimdi geç olduğunu biliyorum, ama nerede durum için daha az ideal bir dize seçtiyseniz sonuçları görmek merak ederdim. "califo [rnia]" ilk karakteri karşılaştırdıktan sonra uyumsuzlukları atabildiği için idealdir, sadece gerçek maçlarda daha fazla kontrol edilmesi gerekir; "newham" gibi bir şey, tüm uyumsuzlukları ortadan kaldırmak için daha fazla karakter karşılaştırmak gibi yeni ilginç sonuçlar verirdi. Ayrıca, tamsayılarınızı bu şekilde sınırlamak, onlara karşı olasılıkları da yığılır, onlara en az 26 değer verirdim.
Uueerdo

15
10 yıllık bir soruda, bu sadece spekülasyon değil, gerçek kriterlere dayanan iki cevaptan sadece biri.
Adrian Baker

1
Ancak tablolarınız, aslında InnoDB'de sıralı bir veri yapısı olan birincil bir anahtara sahip değildir. Tamsayı sıralama ve dize sıralama arasındaki hız farklı olmalıdır.
Melkor

1
@Melkor INDEXBunun yerine kullandığım adil nokta PRIMARY KEY. Muhakememi hatırlamıyorum - muhtemelen PRIMARY KEYsadece INDEXbenzersiz bir kısıtlama olduğunu varsaydım . Ancak, şeylerin federico-razzoli.com/primary-key-in-innodb içindeki InnoDB'de nasıl saklandığına dair bölümü okuduğumda, sonuçlarımın hala birincil anahtarlar için geçerli olduğunu ve değer arama performans farkı hakkındaki soruyu cevapladığını düşünüyorum. Ayrıca, yorumunuz, araştırdığım kullanım durumu için geçerli olmayan , bir kümedeki değerleri arayan sıralama algoritmalarının performansına bakmanızı önerir .
Jan Żankowski

1
Arama işlemi ayrıca int'in varchar'dan biraz daha hızlı olması gereken birincil anahtar alanında (ikili arama gibi) karşılaştırmalar gerektirir. Ancak deneylerinizin önerdiği gibi, bu çok açık değil (veya belki de birincil anahtarınız olmadığı için sorguların daha yavaş olması). Bence ekleme ve aramada da aynı şey geçerli.
Melkor

38

Uzunluğa bağlıdır .. Varchar 20 karakter olacaksa ve int 4 ise, bir int kullanıyorsanız, dizininizde diskteki dizin alanı sayfası başına BEŞ kat fazla olacaktır ... endeks, fiziksel ve / veya mantıksal okumaların beşte birini gerektirir.

Dolayısıyla, fırsat göz önüne alındığında performans bir sorunsa, tablolarınız için ve bu tablolardaki satırlara başvuran Yabancı Anahtarlar için her zaman anlamlı olmayan bir anahtar (yedek olarak adlandırılır) kullanın ...

Aynı zamanda , garanti veri tutarlılığı için, bu konularda her tablo gerektiğini de yinelenen satırlar (anlamlı tablo niteliklere dayalı çoğaltmak) eklenemez emin olmak için anlamlı bir sayısal olmayan alternatif tuşuna (ya da benzersiz Index) sahiptir.

Bahsettiğiniz özel kullanım için (devlet aramaları gibi), tablonun boyutu çok küçük olduğu için gerçekten önemli değil. Genel olarak birkaç bin satırdan az tablolardaki endekslerin performansı üzerinde bir etkisi yoktur. ..


Elbette? En veri formatları satır tabanlı değil mi? Anahtarların yanı sıra başka veriler de var. Faktör 5 ütopik değil mi?
ManuelSchneid3r

1
@ manuelSchneid3r, Ne? Ütopik? Hayır, faktör 5 "ütopik" değildir. Sadece 20'ye 4 bölündü. Peki "veri formatı satır tabanlı" ne anlama geliyor? Endeksler “sıra tabanlı” değil, dengeli ağaç yapılarıdır.
Charles Bretana

36

Kesinlikle hayır.

INT, VARCHAR ve CHAR arasında birkaç ... birkaç ... performans kontrolü yaptım.

Bir PRIMARY KEY (benzersiz ve kümelenmiş) içeren 10 milyon kayıt tablosu, üçünden hangisini kullanırsam kullansam, aynı hız ve performansa (ve alt ağaç maliyetine) sahipti.

Olduğu söyleniyor ... uygulamanız için en iyisini kullanın. Performans hakkında endişelenmeyin.


42
varchars ne kadar uzun olduğunu bilmeden anlamsız ... Eğer 100 bayt genişliğinde olsaydı o zaman 4 bayt int ile aynı performansı elde edemeyeceğiniz garanti
Charles Bretana

6
Ayrıca hangi veritabanını kullandığınızı ve veritabanının hangi sürümünü kullandığınızı bilmenize yardımcı olur. Performans ayarlama neredeyse her zaman üzerinde çalışır ve sürümden sürüme geliştirilir.
Dave Black

VARCHAR kesinlikle dizin boyutu için önemlidir. Ve indeks hafızaya ne kadar sığabileceğini belirler. Ve bellekteki dizinler, olmayanlardan çok daha hızlıdır. 10m satırlarınız için, bu dizin için 250 MB kullanılabilir belleğiniz olabilir ve iyiydi. Ancak 100 metrelik satırlarınız varsa, bu bellekte daha az iyi olacaksınız.
Paul Draper

9

Kısa kodlar için, muhtemelen hiçbir fark yoktur. Bu özellikle, bu kodları tutan tablonun çok küçük olması (en fazla birkaç bin satır) olması ve sık sık değişmemesi (en son ne zaman yeni bir ABD Devleti eklediğimiz) için geçerlidir.

Anahtar arasında daha geniş bir varyasyona sahip daha büyük tablolar için bu tehlikeli olabilir. Örneğin, bir Kullanıcı tablosundan e-posta adresini / kullanıcı adını kullanmayı düşünün. Birkaç milyon kullanıcınız varsa ve bu kullanıcılardan bazılarının uzun adları veya e-posta adresleri varsa ne olur? Şimdi bu anahtarı kullanarak bu masaya katılmanız gerektiğinde çok daha pahalı hale gelir.


2
Bunun pahalı olacağından emin misiniz? Yoksa sadece tahmin mi ediyorsun?
Steve McLeod

Tabii ki rdbms uygulamasına bağlıdır, ancak anladığım kadarıyla çoğu sunucu indeksleme amaçları için gerçek değerin karmasını koruyacaktır. Buna rağmen ve göreceli olarak kısa bir karma (örneğin, 10 bayt) olsa bile, 2 10 baytlık karmayı 244 bayttan daha karşılaştırmak daha fazla iştir.
Joel Coehoorn

ASLA birleştirmeler için uzun (geniş) bir anahtar kullanmayın ... Ancak, tablodaki satırlar için benzersiz olanın en iyi temsili ise, o zaman benzersiz bir anahtar (veya aynı şey olan dizin - daha iyi) Bu doğal değerleri kullanarak tablo. Anahtarlar birleşme için orada değil, kalbinizin istediği her şeye katılabilirsiniz. Veri tutarlılığını sağlamak için anahtarlar vardır.
Charles Bretana

6

Birincil Anahtar'a gelince, fiziksel olarak bir satırı benzersiz yapan her şey birincil anahtar olarak belirlenmelidir.

Yabancı anahtar olarak referans için, otomatik artan bir tamsayıyı vekil olarak kullanmak iki ana nedenden dolayı iyi bir fikirdir.
- İlk olarak, birleştirme işleminde genellikle daha az ek yük oluşur.
- İkincisi, benzersiz varchar içeren tabloyu güncellemeniz gerekiyorsa, güncellemenin tüm alt tablolara basamaklanması ve tüm dizinleri ve dizinleri güncellemesi gerekirken, int vekilinde, yalnızca ana tablo ve dizinleri.

Vekil kullanımının çekilişi, vekilin anlamının değiştirilmesine izin verebilmenizdir:

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

Her şey yapınızda gerçekten endişelenmeniz gereken şeylere ve en çok ne anlama geldiğine bağlıdır.


3

Bir vekilin yaygın olduğu durumlar AUTO_INCREMENT acı :

Ortak bir şema kalıbı, çoktan çoğa eşlemedir :

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

Bu desenin performansı, özellikle InnoDB kullanılırken çok daha iyidir:

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

Neden?

  • InnoDB ikincil anahtarlarının ek bir aramaya ihtiyacı vardır; çifti PK'ye hareket ettirerek, bir yönden kaçınılır.
  • İkincil indeks "kaplamaktadır", bu yüzden fazladan aramaya gerek yoktur.
  • Bu tablo kurtulmak idve bir dizin nedeniyle daha küçüktür .

Başka bir dava ( ülke ):

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

Acemi çoğu zaman INT'doğal' 2 baytlık, neredeyse değişmeyen 2 baytlık bir dize kullanmak yerine country_code'u 4 baytta normalleştirir . Daha hızlı, daha küçük, daha az JOIN, daha okunabilir.


2

HauteLook olarak masalarımızın çoğunu doğal anahtarlar kullanacak şekilde değiştirdik. Performansta gerçek dünyada bir artış yaşadık. Bahsettiğiniz gibi, sorgularımızın çoğu artık daha az birleşim kullanıyor ve bu da sorguları daha performanslı hale getiriyor. Eğer mantıklıysa, bileşik bir birincil anahtar bile kullanacağız. Bununla birlikte, bir vekil anahtarları varsa, bazı tablolarla çalışmak daha kolaydır.

Ayrıca, kişilerin veritabanınıza arayüz yazmasına izin veriyorsanız, yedek anahtar yardımcı olabilir. 3. taraf, vekil anahtarın çok nadir durumlarda değişeceğine güvenebilir.


2

Aynı ikilemle karşılaştım. 3 olgu tablosu, Trafik Kazaları, Kaza Araçları ve Kazalarda Yaralılar ile bir DW (Takımyıldız şeması) yaptım. Veriler, 1979'dan 2012'ye kadar İngiltere'de kaydedilen tüm kazaları ve 60 boyut tablosunu içermektedir. Hep birlikte, yaklaşık 20 milyon kayıt.

Olgu tabloları ilişkileri:

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

RDMS: MySQL 5.6

Yerel olarak Kaza endeksi 15 haneli bir varchar (rakamlar ve harfler). Kaza dizinleri hiçbir zaman değişmeyecekse, yedek anahtarlara sahip olmamayı denedim. Bir i7 (8 çekirdekli) bilgisayarda, boyutlara bağlı olarak 12 milyon yük kaydından sonra DW sorgulamak için çok yavaş hale geldi. Çok fazla yeniden çalışma ve bigint vekil anahtarları ekledikten sonra ortalama% 20 hız performans artışı elde ettim. Henüz düşük performans kazancı, ancak geçerli deneyin. Im MySQL ayarlama ve kümeleme çalışma.


1
Bölümlere bakmanız gerekiyor gibi görünüyor.
jcoffland

2

Soru MySQL ile ilgili, bu yüzden önemli bir fark olduğunu söylüyorum. Oracle (sayıları dize olarak saklayan - evet, ilk başta inanamadım) hakkında ise, o zaman çok fazla fark yok.

Tabloda depolama sorunu değil ama güncelleme ve dizine atıfta bulunulmasıdır. Birincil anahtarını temel alan bir kayda bakmayı içeren sorgular sıktır - bu kayıtların olabildiğince hızlı olmasını istersiniz çünkü çok sık gerçekleşirler.

Mesele şu ki, CPU silikonda 4 bayt ve 8 bayt tamsayılarla ilgileniyor . İki tamsayıyı karşılaştırması GERÇEKTEN hızlıdır - bir veya iki saat döngüsünde gerçekleşir.

Şimdi bir dizeye bakın - çok sayıda karakterden oluşur (bu günlerde karakter başına birden fazla bayt). Öncelik için iki dizeyi karşılaştırmak bir veya iki döngüde yapılamaz. Bunun yerine, bir fark bulunana kadar dizelerin karakterleri yinelenmelidir. Eminim bazı veritabanlarında daha hızlı hale getirmek için hileler vardır, ancak bu ilgisizdir çünkü int karşılaştırması doğal olarak yapılır ve CPU tarafından silikonda yıldırım hızındadır.

Genel kuralım - her birincil anahtar, nesneler arasında çok sayıda ilişkinin olduğu bir ORM (Hazırda Beklet, Datanucleus, her neyse) kullanan OO uygulamalarında otomatik olarak artan bir INT olmalıdır - genellikle her zaman basit bir FK ve Bu hızlı çözümlemek için DB uygulamanızın yanıt verebilirliği için önemlidir.


0

Performans sonuçları hakkında emin değilim, ancak en azından geliştirme sırasında, hem otomatik olarak artırılan, tamsayı "vekil" anahtarını hem de amaçladığınız, benzersiz "doğal" anahtarınızı dahil etmek olası bir uzlaşma gibi görünüyor. Bu, performansı ve doğal anahtarların değiştirilebilirliği de dahil olmak üzere diğer olası sorunları değerlendirme fırsatı verecektir.


0

Her zamanki gibi, battaniye cevapları yok. 'Değişir!' ve ben dehşet verici değilim. Orijinal soruyu anlamam, Ülke (tamsayı kimliği veya karakter / varchar kodu) gibi büyük tablolardaki tuşlar için adres / kişi tablosu gibi potansiyel olarak büyük bir tablonun yabancı anahtarı olmasıydı.

Veritabanından geri veri almak istediğinizde iki senaryo vardır. Birincisi, tüm kişileri eyalet ve ülke kodları veya isimleri ile listelemek istediğiniz bir liste / arama türüdür. Diğeri, devletin, ülkenin adının gösterilmesi gereken tek bir kişi kaydını gösteren birincil anahtardaki bir get senaryosudur.

İkincisi için, FK'nin neye dayandığı önemli değildir, çünkü tek bir kayıt veya birkaç kayıt ve anahtar okumalar için tabloları bir araya getiriyoruz. Önceki (arama veya liste) senaryosu seçimimizden etkilenebilir. Ülkeyi göstermek gerektiğinden (en azından tanınabilir bir kod ve belki de aramanın kendisi bir ülke kodu içerir), bir yedek anahtar aracılığıyla başka bir masaya katılmak zorunda kalmamak potansiyel olarak (burada sadece dikkatli olduğum için test ediyorum) bu, ancak oldukça muhtemel gibi görünüyor) performansı artırmak; aramaya kesinlikle yardımcı olmasına rağmen.

Kodlar boyut olarak küçük olduğundan - genellikle ülke ve eyalet için en fazla 3 karakter olduğundan, bu senaryoda doğal anahtarları yabancı anahtar olarak kullanmak uygun olabilir.

Anahtarların daha uzun varchar değerlerine ve belki de daha büyük tablolara bağlı olduğu diğer senaryo; yedek anahtar muhtemelen avantajlıdır.


0

Evet diyelim ki performansın kapsamı göz önünde bulundurularak kesinlikle bir fark var (Kutudan çıktığı gibi):

1- Kodunuzda veya sorgunuzda ToUpper (), ToLower (), ToUpperInvarient () veya ToLowerInvarient () kullanmanız gerekmediğinden ve bu 4 işlevin farklı performans ölçütlerine sahip olması nedeniyle vekil int kullanımı uygulamada daha hızlıdır. Bununla ilgili Microsoft performans kurallarına bakın. (uygulamanın performansı)

2- Vekil int kullanımı, anahtarın zaman içinde değişmemesini garanti eder. Ülke kodları bile değişebilir, Wikipedia'nın ISO kodlarının zaman içinde nasıl değiştiğini görün. Alt ağaçların birincil anahtarını değiştirmek çok zaman alacaktı. (veri bakım performansı)

3- PK / FK int olmadığında NHibernate gibi ORM çözümleriyle ilgili sorunlar var gibi görünüyor. (geliştirici performansı)

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.