MySQL VARCHAR boyutlarının performans etkileri


45

MySQL'de varchar boyutları arasında performans farkı var mı? Örneğin varchar(25)ve varchar(64000). Değilse, sadece odadan dışarı çıkmamanızı sağlamak için tüm varcharları maksimum boyutta ilan etmemek için bir neden var mı?


3
+1 bu soru tüm DBMS'lere benzer şekilde geçerlidir. Benim gözlemim birçok varkar boyutunun büyümeye meyilli olduğu.
bernd_k

5
MySQL değil, fakat Depesz'in bu blog yazısı PostgreSQL için sorunuza cevap verebilir .
xenoterracide

Yanıtlar:


29

CHAR vs VARCHAR kullanmanın değişmezliğini gerçekleştirmelisin.

CHAR alanları ile tahsis ettiğiniz tam olarak ne elde ettiğinizdir. Örneğin, CHAR (15), alana ne kadar karakter koyduğunuz önemli değil, 15 bayt ayırır ve saklar. Veri alanının boyutu tamamen tahmin edilebilir olduğundan, dize manipülasyonu basit ve kolaydır.

VARCHAR alanları ile tamamen farklı bir hikaye edinirsiniz. Örneğin VARCHAR (15) aslında veri için en fazla 16 bayt, veri için 15 ve en az 1 veri baytını depolar. Eğer saklamak için 'merhaba' dizgesi varsa, 6 bayt alacaktır, 5 değil. Dize manipülasyonu her zaman her durumda bir miktar uzunluk kontrolü yapmalıdır.

İki şeyi yaptığınızda tradeoff daha belirgindir:
1. Milyonları veya milyarlarca satırı saklamak
2. CHAR veya VARCHAR olan sütunların indekslenmesi

TİCARET MARKASI # 1

Açıktır ki, VARCHAR değişken uzunluktaki veriler daha küçük satırlar ve dolayısıyla daha küçük fiziksel dosyalar üreteceğinden avantaj sağlar.

TİCARET MARKASI # 2

CHAR alanları sabit alan genişlikleri nedeniyle daha az dize manipülasyonu gerektirdiğinden, CHAR alanına karşı indeks aramaları VARCHAR alanlarına göre ortalama% 20 daha hızlıdır. Bu benim açımdan herhangi bir varsayım değil. MySQL Veritabanı Tasarımı ve Ayarlaması kitabı bunu kanıtlamak için MyISAM masasında muhteşem bir şey yaptı. Kitaptaki örnek aşağıdaki gibi bir şey yaptı:

ALTER TABLE tblname ROW_FORMAT=FIXED;

Bu yönerge kuvvetleri, CHAR gibi davranacak VARCHAR'lardır. Bunu 2007'deki önceki işimde yaptım ve 300 GB'lık bir masa aldım ve başka bir şeyi değiştirmeden dizin aramalarını% 20 artırdım. Yayınlandığı gibi çalıştı. Ancak, neredeyse iki katı büyüklüğünde bir masa üretti, ancak bu sadece 1 numaralı tradeoff'a geri döndü.

MySQL'in sütun tanımı için neler önerdiğini görmek için depolanan verileri analiz edebilirsiniz. Sadece aşağıdakileri herhangi bir masaya karşı çalıştırın:

SELECT * FROM tblname PROCEDURE ANALYSE();

Bu, tüm tabloyu geçecek ve içerdiği verilere, minimum alan değerlerine, maksimum alan değerlerine ve benzerlerine bağlı olarak her sütun için sütun tanımları önerecektir. Bazen, CHAR vs VARCHAR'ı planlarken sağduyunuzu kullanmanız gerekir. İşte güzel bir örnek:

IP adreslerini saklıyorsanız, böyle bir sütunun maskesi en çok 15 karakterdir (xxx.xxx.xxx.xxx). Bir kalp atışı sırasında tam olarak CHAR (15) 'e atlayacağım çünkü IP adreslerinin uzunluğu o kadar fazla değişmeyecek ve ek bir bayt tarafından kontrol edilen dize manipülasyonunun karmaşıklığı da değişmeyecek. Hala böyle bir sütuna karşı bir PROSEDÜR ANALİZİ () yapabilirsiniz. VARCHAR'ı bile önerebilir. Bu durumda param hala VARCHAR üzerinden CHAR'da olacaktı.

CHAR-VARCHAR sorunları sadece uygun planlama ile çözülebilir. Büyük güç ile büyük sorumluluk gelir (klişe ama gerçek)


4
IP adreslerini saklıyorsanız, onları int'den başka bir şey olarak saklamak için hiçbir neden görmüyorum. Hepsi bir IP adresi. Birçok dilde bir tür ip2int işlevi vardır. Komut satırı çağrısının uygunluğunu istiyorsanız, ABCD'yi dönüştürmek için saklı bir işlem yapmak zor değildir: A pow (256,3) + b pow (256,2) + c * 256 + d
atxdba

1
Err daha fazla mysql kendi ip2int işlevi vardır sanırım daha fazla: INET_ATON
atxdba

3
@ atxdba: Cevabımın amacı sadece CHAR vs VARCHAR kullanıyor. IP'yi sadece bir örnek olarak kullanıyorum çünkü karakter dizisi büyüklüğü 15'e yaklaşıyor. Bu nedenle VARCHAR lehine sabit bir CHAR boyutunu yuvarlamak sadece sorunun kendisi için bir örnek. IP adreslerini temsil etmenin daha iyi yolları hakkındaki yorumunuz oldukça geçerlidir ve en anlamlı olanıdır.
RolandoMySQLDBA

CHAR (15) , bayt değil 15 karakter ayırır . Utf8 için bu 45 bayttır .
Rick James

2
Bu CHAR / VARCHAR karşılaştırması hakkında iyi bir cevap olsa da, soru farklı VARCHAR boyutları hakkındaydı.
Koleksiyoner

13

Bunun cevabı aslında oldukça karmaşık. Kısa versiyon: bir fark var .

  1. Sonuçları filtrelemek için geçici tablolar oluştururken (örneğin GROUP BYifadeler), tam uzunluk tahsis edilecektir.

  2. Kablo protokolü (müşteriye satır gönderme) büyük olasılıkla daha büyük uzunluk tahsis edecektir.

  3. Depolama motoru uygun bir varchar uygulayabilir / uygulayamaz.

(2) Tel protokolün yakından tanıdığım bir şey olmadığını itiraf ediyorum, ancak buradaki genel tavsiye, uzunluğu tahmin etmek için en azından biraz asgari çabayı denemek ve uygulamak.


İşaret değer. MySQL 5.7, sıralama arabelleğindeki değerleri paketleyebilir (değişken uzunluk). Burada daha ayrıntılı olarak açıklanmaktadır: mysqlserverteam.com/…
Morgan Tocker

9

Bu konudaki cevapların çoğu 5 yaşında, InnoDB ve utf8 önceden yazılmış. Öyleyse, baştan başlayayım ...

Bir sorgu, dahili bir geçici tabloya ihtiyaç duyduğunda, bir tablo kullanmaya çalışır MEMORY. Ancak MEMORY kullanılamazsa

  • TEXT/ BLOBsütunlar bile alınmıyor TINYTEXT.
  • VARCHAR bir miktardan daha büyük, muhtemelen geçerli sürümde 512.

Ayrıca, VARCHARsdönüştürülmüş olduğuna dikkat edin CHARs. Yani, VARCHAR(255)bir ile CHARACTER SET utf8bakılmaksızın sütunda ne olduğu 765 bayt için genişletir. Ardından, bu tetiklenebilir:

  • Eğer MEMORYmasa ikisinden de büyürse ya max_heap_table_size da tmp_table_size MyISAM'a dönüştürülür ve potansiyel olarak diske dökülür.

Öyleyse, VARCHAR(25)kalması daha muhtemeldir MEMORY, dolayısıyla daha hızlı olur. (255)kadar iyi değil ve (64000)kötü.

(Gelecekte, temp tabloları muhtemelen olacak InnoDBve bu cevabın bir kısmının gözden geçirilmesi gerekecek.)


6

Büyüklüğünde bir varchar sütunu tüm tablodaki sorguları geçici tabloları kullanma olasılığını arttırır. Yüksek Performanslı MySQL kitabına göre. Doktor bu sorguyu bellekte çalıştırabilir mi yoksa geçici bir tabloya mı ihtiyaç duyacağını görmeye çalıştığında, tablo tanımına göre satır boyutuna bakar, yani hız için 64K karakterlerinin ne kadarını görmeye çalışmadığını aslında kullanıyorsun. Bu nedenle, yazarlar bu tanımı sütuna girebilecek gerçek değerlerin ötesine uzatmamanızı önermektedir. Açıkçası, kendinizi geçici tablolara giren daha fazla sorgu için ayarladıysanız (gerçek veri boyutu RAM'e sığsa bile), şimdi kaçınılması gereken G / Ç cezalarına çarptınız.


Bu çok taze bir bakış açısı. Bu atıfta bulunduğunuz kitap ise ( amazon.com/MySQL-High-Aepend-Building-Centers/dp/… ), lütfen kitabın sayfa numarasını cevabınıza koyun, çünkü bunu okumak istiyorum. +1 !!!
RolandoMySQLDBA 19:11

Aptal ben… Yüksek PERFORMANS kullanılabilirliği yok: amazon.com/High-Performance-MySQL-Optimization-Replication/dp/…… sayfa numarası 236/237 Varchar sütunu tanımlanmasındaki cömertliğin nasıl yönetilemeyeceğini açıklıyor. Bu kitabın 5.1 henüz dışarı çıktığında yazıldığını unutmayın. Gelecek sene üçüncü basımda, 5.5'teki BÜYÜK değişikliklerin hepsini içerecek şekilde geliyor, belki de değişebilir :)
TechieGurl

Sayfa 236, belirli karakter kümelerine ait harmanlamadan bahseder. Bu VARCHAR için kötü olabilirdi. 237 Sayfasında, istemci / sunucu iletişimi ayarları, Şekil 5-5 sayfa 238 ile birlikte başka bir neden gösterir. Karakter çevirme işlemi ileri geri koyar. Yine, VARCHAR için başka kötü bir macera.
RolandoMySQLDBA 20:11

Netleştirmek için, bu bölüm MySQL'in yaratma boyutuna uygun olduğunu açıkça söylemese de, bir işlemin geçici bir masaya ihtiyacı olduğunda, bu masanın MEMORY Engine'de olduğunu ve BU da her zaman sabit cilalardaki dizge tiplerini sakladığını biliyoruz. tanımı, gerekli MEMORY geçici tablosunun RAM'de kalmak yerine diske gitmesine neden olabilir
TechieGurl

@RolandoMySQLDBA. Evet… o da… harmanlama burada da bir faktör haline gelir (özellikle UTF-8 kullanıyorsanız ve latin olmayan karakterleriniz varsa) ve hepsi sadece bir bellek motoru tablosu ile uğraşırken sizi öldürür ve diske daha hızlı bir geziye yol açar
TechieGurl

5

Anladığım kadarıyla daha küçük alanlar doğrudan endekse dahil olabilir, oysa daha uzun olanları olamaz. Bu sınırlama nedeniyle, dizelerin endekslenebilir olmasını istiyorsanız, onları daha kısa tutun derim. Aksi takdirde, hayır, her ikisinin de varchar olduğu gibi, sıralama veya karşılaştırma gibi işlemler, alanların 25 veya MAX olması durumunda aynı zamanda çalışır.


3

oda tükenmediğinden emin ol

Bu cümle, soruyu sorduğunuza işaret eder çünkü veritabanında saklayacağınız verilerden emin değilsiniz. Eğer bu doğruysa, en kısa sürede öğrenmeniz iyi olacaktır, çünkü kapasite planlaması için buna ihtiyacınız olacak. Örneğin, 7000 karakterden oluşan veri öğeleri alıyorsanız, bunun herhangi bir DBMS üzerinde performans etkisi yaratacağı için bilmeniz gerekir.

Bu, beklenen içerikle ilgili sütun boyutlarına sahip olmayı tercih ettiğimi söyledi. Örneğin, bir ülke kodu ve dahili numara eklemiş olsanız bile, bir telefon numarasının 50 karakterden uzun olması muhtemel değildir. Benzer şekilde, bir posta kodu veya posta kodu büyük olasılıkla 20 karakter veya daha az olacaktır.

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.