MySQL tablosundaki varchar uzunluğunun önemi


112

Satırların dinamik olarak eklendiği bir MySQL tablom var. Tellerin uzunluğundan emin olamadığım ve kesilmesini istemediğim için genellikle ihtiyacım olandan çok daha büyük olan varchar (200) yapıyorum. Bir varchar alanına gerekenden çok daha fazla uzunluk vermede büyük bir performans artışı var mı?


VARCHAR(255) utf8mb4~ 150.000 satıra sahip tek bir indekslenmiş sütuna sahip bir tablo 11.5MB olarak ölçülmüştür. VARCHAR(48) utf8mb4Aynı verilere (maksimum uzunluk 46 karakter) sahip indekslenmiş bir sütuna sahip bir tablo 4.5MB kullandı. Sorgularda gerçekten büyük bir fark değil, dizine alınmış. Ancak, sorgu G / Ç ve veritabanı yedeklemeleri gibi şeylerle birleşir.
Code4R7

Yanıtlar:


59

Hayır, o sütunda sakladığınız değerler her zaman (örneğin) 50 karakterden azsa, sütunu olarak varchar(50)veya varchar(200)aynı performansa sahip olarak bildirmek anlamında .


9
Tam olarak doğru değil. Bill
Karwin'in

5
Bence gibi bir yanıt, dokümanlar, ölçütler veya benzer bir şeyle desteklenmelidir.
Gökhan Sarı

301

Olası bir performans etkisi vardır: MySQL'de, geçici tablolar ve MEMORYtablolar bir VARCHARsütunu, maksimum uzunluğuna kadar doldurulmuş sabit uzunlukta bir sütun olarak depolar . İhtiyaç VARCHARduyduğunuz en büyük boyuttan çok daha büyük sütunlar tasarlarsanız , gerekenden daha fazla bellek tüketirsiniz. Bu, önbellek verimliliğini, sıralama hızını vb. Etkiler.


33
+1. Satırları almak için arabellekleri kurarken maksimum boyut için yeterli alan ayıran bazı JDBC sürücüleri de görünüyor. Söylemeye gerek yok, bir palyaço az önce varchar (50000) yaptığında, birisinin soyadı gerçekten büyükse :-)
paxdiablo

21
+1. Bu önemli bir etki ve bence bu sorunun gerçek cevabı bu.
Emre Yazıcı

6
Bu cevap ve kabul edilen cevap, OP'ye verilen doğru cevabı anlamak için gereklidir.
kd8azz

2
Aslında böyle bir MEMORYtablo çok büyük kabul edildiğinde diske yazılır ve önemli performans düşüşüne neden olur.
Timo

1
Bu cevap, hangi depolama motorlarının doğru olduğunu belirtmekle işe yarayabilir ( dev.mysql.com/doc/refman/8.0/en/… ' nin MySQL 8 itibariyle geçici tabloların her zaman InnoDB olduğunu gösterdiğini unutmayın ; bu herhangi bir şeyi değiştirir mi?) ve öne sürdüğü iddiaları destekleyen dokümanların bağlantılarıyla. Stack Exchange'deki çıktınız hakkında gördüğüm kadarıyla, bunu yazdığınızda haklı olduğunuza inanıyorum, ancak işler değişmiş olabilir ve bağlantılar hem başkaları için iyi bir örnek oluşturacak hem de geri kalanımıza bulmayı öğretmeye yardımcı olacaktır. kendimiz için bu tür bilgiler.
Mark Amery

14

VARCHAR, tanımladığınız durum için idealdir, çünkü "değişken karakter" anlamına gelir - örneğinize göre sınır 200 karakter olabilir, ancak daha azı kabul edilir ve sütunun ayrılan boyutunu doldurmaz.

VARCHAR ayrıca daha az yer kaplar - değerler bir baytlık veya iki bayt uzunluğunda ön ek artı veri olarak saklanır. Uzunluk öneki, değerdeki bayt sayısını gösterir. Değerler 255 bayttan fazlasını gerektirmiyorsa sütun bir uzunluk baytı, değerler 255 bayttan fazlasını gerektiriyorsa iki uzunluk baytı kullanır.

MySQL CHAR ile VARCHAR veri türlerini karşılaştırmak için daha fazla bilgi için bu bağlantıya bakın .


1
MySQL depolamayla ilgilenen herkes (CHAR ve VARCHAR hakkında) bu yanıtta belirtilen bağlantıyı okumalıdır. Teşekkürler!
Pascal

14

Boyut performanstır! Boyut ne kadar küçükse o kadar iyidir. Bugün ya da yarın değil, ama bir gün, hangi tasarımı hazırlarsanız tasarlayın, ciddi darboğazlar söz konusu olduğunda masalarınız bir boyuta ulaşacak. Ancak, tasarım aşamanızda ilk olarak gerçekleşmesi muhtemel olan bazı potansiyel darboğazları öngörebilir ve daha fazla sunucu ekleyerek planınızı yeniden düşünmeniz veya yatay olarak ölçeklendirmeniz gerekene kadar db'nizin hızlı ve mutlu bir şekilde gerçekleştireceği zamanı uzatmaya çalışabilirsiniz.

Sizin durumunuzda karşılaşabileceğiniz birçok performans sızıntısı vardır: Uzun varcharkolonlarda büyük birleşimler neredeyse imkansızdır . Bu sütunların indekslenmesi gerçek bir katildir. Diskinizin verileri depolaması gerekir. Bir bellek sayfası daha az satır tutabilir ve tablo taramaları çok daha yavaş olacaktır. Ayrıca sorgu önbelleğinin burada size yardımcı olma olasılığı düşüktür.

Kendinize şunu sormalısınız: Yılda kaç ek olabilir? Ortalama uzunluk nedir? Gerçekten 200'den fazla karaktere ihtiyacım var mı yoksa kullanıcıları maksimum uzunluk hakkında bilgilendirerek bile uygulamamın ön ucunda bunu yakalayabilir miyim? Hızlı indeksleme ve tarama için tabloyu dar bir tabloya ve genişleyen boyutta daha az sıklıkla ihtiyaç duyulan ek verileri tutmak için başka bir tabloya ayırabilir miyim? Olası varchar verilerini kategorilere yazabilir ve böylece verilerin bir kısmını birkaç küçük, belki int veya bool tipi sütuna çıkarabilir ve varchar sütununu bu şekilde daraltabilir miyim?

Burada çok şey yapabilirsiniz. İlk varsayımla gitmek ve ardından gerçek hayattan ölçülen performans verilerini kullanarak adım adım yeniden tasarlamak en iyisi olabilir. İyi şanslar.


Tasarım seçeneklerini listelemek ve etkiyi keşfetmek için +1. Sorum için de çok yardımcı oldu. stackoverflow.com/q/12083089/181638
Assad Ebrahim

5
Yüksek bir maksimum uzunluk ayarlamanın gerçek performans etkisi var mı yoksa performans yalnızca gerçek boyuta göre mi belirleniyor?
poolie

5

Verim? Hayır. Disk depolama? Evet, ama ucuz ve bol miktarda. Veritabanınız terabayt ölçeğine ulaşmadıkça muhtemelen iyisinizdir.


Bu cevabın yayınlandıktan altı yıl sonra reddedilmesi ve diğerlerinden hiçbirinin almaması garip. Kinci ve önemsiz görünüyor. Bu cevapta yanlış bir şey yok. Moderatörler?
duffymo

1
Söylendiği gibi performansı etkiliyor. Ayrıca, disk depolaması da ücretsiz değildir. Daha geniş bir sütun, daha fazla disk okuma / yazma (ve disk erişimi slooooooow) ve ayrıca kullanışlılıklarını azaltan daha geniş dizinler anlamına gelir. Her iki şey de performansı olumsuz etkiler. Belki küçük bir veritabanında bu önemsizdir, ancak sizin de söylediğiniz gibi gigabayt / terabayt ölçeğinde kesinlikle önemli olacaktır. 100 kayıt tablosu için önemli değil.
Alejandro

5

Bazılarınız, a'nın varchar(200)diskte a'dan daha fazla tablo boyutu kapladığını düşünerek yanılıyor varchar(20). Olay bu değil. Yalnızca 255 karakterin ötesine geçtiğinizde mysql, varcharalan verilerinin uzunluğunu belirlemek için fazladan bir bayt kullanır .


9
Geçici tablolar ve MEMORYtablolar için öyle değil .
Orbit'te Hafiflik Yarışları

4
Seçtiğiniz sorgu geçici bir tablo kullandığında (diğer şeylerin yanı sıra işlemlere göre gruplama ve sıralama) varchar (200) 'ü bir char (200)' e dönüştürür ve performans düşer.
Jamie

1

Performans isabetleri olabilir - ancak genellikle çoğu kullanıcının fark edeceği düzeyde değildir.

Her alanın boyutu önceden bilindiğinde, MySQL her alan / satır arasında tam olarak kaç bayt olduğunu bilir ve tüm verileri okumadan ileriye sayfalara gidebilir. Değişken karakterlerin kullanılması, optimizasyon için bu yeteneği azaltır.

Varchar, veri parçalanması nedeniyle performansın düşmesine neden oluyor mu?

Daha da iyisi, char vs varchar .

Birçok kullanım için, biriyle iyi olacak - ama orada olduğunu fark ve büyük ölçekli veritabanları için, birini ya da diğer alacağını neden nedenleri vardır.


0

Varchar olduğundan, boyut, gerçek uzunluğunu ve dizenin kendisini belirtmek için dahili bir alana dayanır. Dolayısıyla varchar (200) kullanmak, daha fazlasını saklama potansiyeline sahip olmanız dışında varchar (150) kullanmaktan çok farklı değildir.

Ve bir satır büyüdüğünde bir güncellemede ne olacağını düşünmelisiniz. Ancak bu nadirse, o zaman iyi olmalısın.


0

veri türü adından da anlaşılacağı gibi, bunun VARCHAR olduğunu, yani değişken karakter veri depolamasını, mysql motorunun kendisi depolanan verilere göre kullanılan belleği tahsis eder, bu nedenle bilgime göre performans artışı olmaz.


0

Çoğu senaryoda bir char sütununda yaptığınız gibi bir varchar sütununu görüntülemeye çalışmalı ve uzunluğu ölçülü bir şekilde ayarlamalısınız. Her zaman var değiştiriciyi, karar vermenizi maksimum uzunlukta etkileyen bir şey olarak düşünmek zorunda değilsiniz. Sağlanan dizelerin farklı uzunluklarda olacağı gerçekten bir performans ipucu olarak görülmelidir.

Veri tabanı içindekiler tarafından sıkı sıkıya uyulması gereken bir yönerge değildir, tamamen göz ardı edilebilir. Bununla birlikte, ideal bir dünyada olmaması gerekmesine rağmen bazen uygulama sızıntı yapabileceğinden (örneğin sabit uzunluk ve dolgu) buna dikkat edin.

Bir varchar (255) 'e sahipseniz, performans açısından her koşulda bir char (255) için her zaman farklı davranacağını garanti edemezsiniz.

Kılavuzda depolama gereksinimleri hakkında verilen tavsiyeler doğrultusunda 255, 65535, vb. Gibi bir şeye ayarlamak kolay görünebilir. Bu, 0 (evet, bu bir şey) ile 255 arasındaki herhangi bir değerin aynı etkiye sahip olacağı izlenimini verir. Ancak bu tamamen garanti edilebilecek bir şey değildir.

Depolama gereksinimleri, satır depolama açısından düzgün ve olgun kalıcı depolama motorları için doğru olma eğilimindedir veya iyi bir gösterge olma eğilimindedir. Dizinler gibi şeyler için o kadar güçlü bir gösterge değildir.

Bazen zor bir sorudur, bir ip parçası tam olarak ne kadar uzun olmalıdır ki, onu içinde olması gerektiğini bildiğiniz en yüksek sınıra ayarlamak, ancak bunun hiçbir etkisi yoktur. Ne yazık ki bu genellikle kullanıcının yapması gereken bir şeydir ve gerçekten biraz keyfi bir durumdur. Bir dizeyi asla büyütme diyemezsiniz çünkü tam olarak emin olmadığınız durumlar olabilir.

MySQL sorgularının, bir dizi çok uzun olduğunda, kesilmek yerine bir hata attığından emin olmalısınız, böylece en azından hata emisyonlarından çok kısa olup olmadığını bilirsiniz. Sütunları büyütmek veya küçültmek için yeniden boyutlandırmak pahalı bir DDL işlemi olabilir, bu akılda tutulmalıdır.

Uzunluk ve performansın devreye girdiği yerde karakter seti de dikkate alınmalıdır. Uzunluk, bayt yerine bunu ifade eder. Örneğin utf8 kullanılıyorsa (MB4 değil), o zaman varchar (255) gerçekten değişken ikili (3 * 255) 'dir. Testler yapmadan ve kaynak koduna / belgelere derinlemesine bakmadan böyle şeylerin nasıl sonuçlanacağını bilmek zor. Bu nedenle, beklenmedik şekilde şişirilmiş bir etkiye sahip olmak için aşırı uzunluğun kapsamı vardır. bu sadece performans için geçerli değildir. Bir gün bir varchar sütununun karakter kümesini daha büyük bir değere değiştirmeniz gerekiyorsa, gereksiz yere uzun dizelerin mevcut olmasına izin verdiyseniz, kaçınılabilecek herhangi bir rücu olmadan bir sınıra ulaşabilirsiniz. Bu normalde oldukça niş bir sorundur ama ortaya çıkıyor,

MAX (LENGTH (sütun)) değerinin her zaman <64 olduğu ortaya çıkarsa (örneğin, sütun tanımıyla eşleşmeyen bir girdi sınırı olacağına karar verilmişse), ancak varchar (255) varsa, o zaman bir Bazı senaryolarda gerekenden dört kat daha fazla alan kullanma şansınız yüksektir.

Bu şunları içerebilir:

  • Farklı motorlar, bazıları tamamen görmezden gelebilir.
  • Tampon boyutları, örneğin güncelleme veya ekleme tam 255'i tahsis etmek zorunda kalabilir (bunu kanıtlamak için kaynak kodunu kontrol etmemiş olsam da, bu sadece bir varsayımdır).
  • Dizinler, çok sayıda varchar (255) sütundan bir bileşik anahtar yapmaya çalışırsanız, bu hemen anlaşılacaktır.
  • Ara tablolar ve olası sonuç kümeleri. İşlemlerin çalışma şekli göz önüne alındığında, bir şeyin tanımlanan sınırın aksine bir sütundaki dizelerin gerçek maksimum uzunluğunu kullanması her zaman mümkün olmayabilir.
  • Dahili tahmin optimizasyonları, maksimum uzunluğu girdi olarak alabilir.
  • Veritabanı uygulama versiyonlarındaki değişiklikler.

Genel bir kural olarak, bir varchar'ın olması gerekenden daha uzun olmasına gerçekten gerek yoktur, performans sorunları olsun ya da olmasın, bu yüzden mümkün olduğunda buna bağlı kalmanızı öneririm. Verilerinizin boyutunu örneklemek, gerçek bir sınır uygulamak veya sorarak / araştırarak gerçek sınırı bulmak için daha fazla çaba sarf etmek ideal yaklaşımdır.

Yapamadığınızda, şüpheli durumlarda varchar (255) gibi bir şey yapmak istiyorsanız, o zaman bilim yapmanızı tavsiye ederim. Bu, tabloyu çoğaltmaktan, var char sütununun boyutunu küçültmekten ve ardından veriyi orijinalden içine kopyalamaktan ve dizin / satır verilerinin boyutuna bakmaktan (sütunu indeksleyin, ayrıca bunu birincil anahtar olarak deneyin) içerebilir. satırlar birincil anahtara göre sıralandığından InnoDB'de farklı davranabilir). En azından bu şekilde, en hassas darboğazlardan biri olma eğiliminde olan IO üzerinde bir etkinizin olup olmadığını anlayacaksınız. Bellek kullanımını test etmek daha zordur, bunu kapsamlı bir şekilde test etmek zordur. Olası en kötü durumları test etmenizi tavsiye ederim (bellek sonuçlarında çok sayıda ara sonuç içeren sorgular, büyük geçici tablolar için açıklamayla kontrol edin, vb.).

Tabloda çok fazla satır olmayacağını biliyorsanız, sütunu birleşimler, dizinler (özellikle bileşik, benzersiz), vb. İçin kullanmayacaksınız, o zaman büyük olasılıkla pek çok sorun yaşamayacaksınız.

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.