İlişkisel veritabanları, her sütun için önceden tanımlanmış bir veri türü ayarlayarak ne kazanır?


44

Şu anda bir SQL veritabanı ile çalışıyorum ve bu beni her zaman meraklandırdı, ancak Google aramaları pek fazla ortaya çıkmıyor: Neden katı veri türleri?

İkili ve düz metin verisi arasındaki farkın ne kadar önemli olduğu gibi neden birkaç farklı veri türünüz olduğunu anlıyorum . İkili verilerin 1'lerini ve 0'larını düz metin olarak saklamak yerine, artık ikili verileri kendi biçiminde saklamanın daha verimli olduğunu anladım.

Ama ya yok anlamaya yarar sahip budur pek çok farklı veri türleri:

  • Neden mediumtext, longtextve text?
  • Neden decimal, floatve int?
  • vb.

Veritabanına “Bu sütuna yapılan girişlerde yalnızca 256 bayt düz metin verisi olacak” demesinin faydası nedir? veya "Bu sütun, 16.777.215 bayta kadar metin girişleri içerebilir"?

Performans avantajı mı? Öyleyse, elden önce girişin boyutunu bilmek neden performansa yardımcı oluyor? Ya da tamamen başka bir şey mi?


2
Bu sorunun zaten burada bulunması gerektiğini düşündüm, ancak siteyi aradım ve yararlı bir şey bulamadım.
john doe


6
Eğer farklı olmasaydı decimal, floatve inttürlerini, ne beklediğiniz 1 / 3yapmalı? Ne hakkında 1.0 / 3.0? Eğer bölmek zaman emin olabilir columnAtarafından columnBbu beklenmedik sonuçlar elde edersiniz?
Andrew Piliser,

2
@johndoe Hiç gerekli olacağını sanmıyorum, ama çok uygun olabilir. Diyelim ki bir mağazanın envanterinin aylık beklenen satışlarının% 5'inden düşük olamayacağı konusunda bir kısıtlama uygulamak istediğinizi varsayalım. Veya her bölümün toplam bütçesinin toplam bütçenin% 20'sinden fazla olmamasını sağlamak istersiniz. Aynı veritabanını kullanarak birkaç uygulamada aynı şekilde hesaplamak istediğiniz hesaplanmış sütunlarda da ortaya çıkabilir.
Andrew Piliser

2
SQLite belirterek It yetmeyecek gelmez Sütun başına önceden tanımlanmış türünü ayarlamak : "SQLite olan 'typeless' ne olursa olsun o sütunun ilan veri türü, herhangi bir tablonun herhangi sütununda istediğiniz her türlü veri saklayabilir olduğunu bu araçlar.. "
Başbakan

Yanıtlar:


50

SQL bir olduğu statik olarak yazılan dil. Bu, kullanmadan önce ne tür bir değişken (veya bu durumda alan) olduğunu bilmeniz gerektiği anlamına gelir. Bu, dinamik olarak yazılmış dillerin tam tersi, burada mutlaka böyle bir durum söz konusu değil.

Temelinde SQL, ilişkisel bir veritabanı motorunda veri ( DDL ) ve erişim verilerine ( DML ) tanımlamak için tasarlanmıştır . Statik yazım, bu tip bir sisteme dinamik yazmaya göre çeşitli avantajlar sunar.

  • Belirli kayıtlara hızla erişmek için kullanılan dizinler , boyut düzeltildiğinde gerçekten iyi çalışır. Muhtemelen birden fazla alan içeren bir dizin kullanan bir sorgu düşünün: veri türleri ve boyutları önceden biliniyorsa, yüklemimi (WHERE yan tümcesi veya JOIN ölçütleri) dizindeki değerler ile çok hızlı bir şekilde karşılaştırabilir ve istenen kayıtları daha hızlı bulabilirim .

  • İki tamsayı değeri göz önünde bulundurun . Dinamik tipte bir sistemde değişken büyüklükte olabilirler (Java'yı BigIntegerveya Python'un yerleşik isteğe bağlı tam sayılarını düşünün ). Tamsayıları karşılaştırmak istersem, önce bit uzunluklarını bilmem gerekir. Bu, büyük ölçüde modern diller tarafından gizlenen, ancak CPU düzeyinde gerçek olan bir tamsayı karşılaştırmanın bir yönüdür. Boyutlar önceden belirlenmiş ve zamanından önce biliniyorsa, işlemden bütün bir adım kaldırılır. Yine, veritabanlarının zillions işlemlerini olabildiğince hızlı bir şekilde işleme koyabilecekleri düşünülmektedir. Hız kraldır.

  • SQL 1970'lerde geri tasarlandı. Mikrobilgisayarın ilk günlerinde, bellek çok fazlaydı. Verilerin sınırlandırılması, depolama gereksinimlerinin kontrol altında tutulmasına yardımcı oldu. Bir tamsayı asla bir bayttan daha fazla büyümezse, neden bunun için daha fazla depolama ayırmalısınız? Bu sınırlı hafıza çağında boşa harcanan alandır. Modern zamanlarda bile, fazladan boşa harcanan bu baytlar bir CPU'nun önbelleğinin performansını artırabilir ve öldürebilir. Unutmayın, bunlar sadece küçük gelişim ortamınız için değil, saniyede yüzlerce işleme hizmet verebilecek veritabanı motorlarıdır.

  • Sınırlı depolama satırları boyunca, hafızada tek bir sayfaya tek bir kayıt sığdırmak faydalı olacaktır. Bir sayfa üzerinden geçtiğinizde, daha fazla sayfa özeti ve daha fazla yavaş bellek erişimi olur. Daha yeni motorlar bu sorunu daha az yapmak için optimizasyonlara sahiptir, ancak hala oradadır. Verileri uygun şekilde boyutlandırarak bu riski azaltabilirsiniz.

  • Moreso modern zamanlarda SQL, ORM veya ODBC veya başka bir katman aracılığıyla diğer dillere bağlamak için kullanılır . Bu dillerden bazılarının güçlü, statik türler gerektirme kuralları vardır. Dinamik olarak yazılmış diller, diğerlerinden daha kolay statik tiplerle başa çıkabildiğinden daha katı gereksinimlere uymak en iyisidir.

  • SQL statik yazmayı destekler çünkü veritabanı motorları performans için yukarıda gösterildiği gibi ihtiyaç duyarlar.

Edilir SQL uygulamalar olduğunu ilginçtir değil kesinlikle yazılan. SQLite muhtemelen böyle bir ilişkisel veritabanı motorunun en popüler örneğidir. Daha sonra, tek bir sistemde tek iş parçacıklı kullanım için tasarlanmıştır, bu nedenle performans kaygıları, örneğin dakikada milyonlarca talebe hizmet veren kurumsal bir Oracle veritabanında olduğu kadar açık olmayabilir.


SQLite, sayısal ve metin verilerini birbirinden ayıran veri türlerine sahip ancak veri depolama alanında yalnızca 5 "sınıf" var: sqlite.org/datatype3.html
FrustratedWithFormsDesigner

1
@FrustratedWithFormsDesigner Biliyorum, ancak SQL Server, Oracle veya PostgreSQL gibi motorlar kadar katı bir yer değil.

Yalnızca SQL statik olarak yazılmaz, kontrol kısıtlamalarının varlığından dolayı, arıtma türlerini etkili bir şekilde destekler.
gardenhead

4
İlk mermide ima edilmesine rağmen Indexes, daha temelde ifade edilir: Veri türüne sahip olmak, veritabanı motorunun verileri anlamasına, karşılaştırmalar yapmasına olanak sağlar (daha büyük / daha küçük sayılar, daha önceki / sonraki tarih-zamanları, alfabe öncesi / sonrası), ve bu nedenle sıralama ve sorgulamayı mümkün kılar .
Basil Bourque

Öyleyse boyutlar önemliyse ... ve sql'nin önceden bilmesi gerekiyorsa ... "Zillion" işlemlerinin gerçek boyutu nedir?
WernerCD

24

İlk olarak: düz metin ikilidir (UTF8 veya ASCII karakterleri "0" ve "1" bile değil, gerçek açma / kapama bitleridir)

Bu, bazı nedenlerin şöyle olduğunu söyledi:

  • İşletme / tasarım kısıtlamaları: PERSON tablasının YÜKSEK sütununda 7626355112 numarasının belirtilmesi yanlış olur. Bir INVOICE DATE sütununda "Howya" izin vermek yanlış olur.
  • Daha az hata eğilimli kod: bir tarih sütundan elde edilen verilerin gerçekten bir tarih olduğundan emin olmak için kod yazmanız gerekmez. Sütun türleri dinamik olsaydı, bunları okurken çok sayıda tür kontrolü yapmanız gerekirdi.
  • Bilgi işlem verimliliği: Eğer bir sütun INTEGER türünde ise ve bunu SUM () ise, RDBMS kayan nokta aritmetik uygulamasına gerek yoktur.
  • Depolama verimliliği: bir sütunun VARCHAR (10) olduğunu belirterek RDBMS'nin alanı daha kesin olarak tahsis etmesini sağlar.
  • Referans bütünlüğü ve birliği: Bir tablonun PK (veya FK'leri ), yüzer nokta eşitliği zor olduğu için yüzdürmeye izin vermemelidir, bu nedenle karakterleri veya tam sayıları gibi kayan olmayan bir tür olarak bildirmeniz gerekir.
  • Dinamik (katı olmayan) sütun tiplerinde (SQLite) RDBMS'ler bulunmaktadır . Şikayet etmeden herhangi bir sütuna neredeyse her şeyi eklemenize izin verirken, "tür benzeşimi" kavramını kullanır. Burada tartışılmayacak takaslar var. Bu soruya bakınız .

8

Veritabanının yazıldığı temel kodun, belirli bir alanın 0 ila 256 karakter içerebildiğini bilmesi durumunda, sabit boyutlu kayıtları tahsis edip kullanabilmesi, böylece depolamak için 256 baytlık bir blok ayırabilir.

Bu, işleri çok daha hızlı hale getirir, örneğin, kullanıcı yazarken ek depolama alanı ayırmak zorunda değilsiniz, çünkü verilen bir alan her zaman x byte'ı bir arama kaydına başlatır ya da o alanda seçim yapar, her kayıt için her zaman x byte'ı kontrol etmeyi bilir.


Keşke tüm cevaplar bu kadar kısa ve öze olabilirse ...
Darren Ringer

6

Bir veritabanının sütunlarına tanımlı türler verildiğinde, türler genellikle bit olarak belirli bir boyuta sahip olacak şekilde tanımlanır. Sonuç olarak:

1) veritabanı motoru bir tablodaki satırları geçtiğinde, her bir kaydın nerede biteceğini belirlemek için herhangi bir fantezi ayrıştırması yapmak zorunda değildir, sadece her satırın 32 bayttan oluştuğunu ve böylece Bir sonraki kaydın o anki kayıt konumuna 32 bayt eklemek yeterlidir.

2) Bir satırdaki bir tarlaya bakarken, hiçbir şey ayrıştırılmadan tekrar o alanın tam bir ofsetini bilmek mümkündür, bu nedenle sütun aramaları potansiyel olarak pahalı bir veri işleme yerine basit bir aritmetik işlemdir.


Sabit uzunluklu alanlar, tutarlı kayıt uzunlukları ve alan kaymaları nedeniyle işlemi daha verimli hale getirebilir, ancak değişken uzunluklu alanlar, kayıt uzunluğu ve alan kayması değişebileceği için bu yararları iptal edebilir. Benzer şekilde, kayıt seviyesi sıkıştırma değişken uzunluklu kayıtlara neden olur, bu nedenle belirli bir kaydın konumu basitçe hesaplanamaz.
Zenilogix

Bu doğrudur ve değişken uzunluktaki alanlardan tam olarak bu nedenle kaçınmak uzun süredir tavsiye edilirdi. Büyük oyuncuların bunu nasıl yaptığını bilmiyorum ama sabit uzunluktaki bazı avantajları motorun değişken genişlikteki alanları kullanıcı tarafından görülemeyen bir tabloda veya bellek bloğunda saklayarak yeniden kazanabiliyor olabilirsiniz. bu alanların birincil tabloları, içine (sabit genişlikte) 'işaretçi' gösterimidir. Düzenli aralıklarla değişken uzunluklu tarlaların düzenli olarak tam taraması yapmanız gerektiğini dikkate alarak, ilk önce indirimin performansının sabit genişliklerin korunmasına değer olabileceğini unutmayın.
UserNotFound

3

DBMS'lerde neden statik veri tipleri olduğunu sordunuz .

  1. Arama hızı. Bir DBMS'nin amacı, bir programa yükleyebileceğinizden çok daha fazla veri depolamaktır. "Son on yılda dünyada üretilen tüm kredi kartı fişlerini" düşünün. Bu tür verileri verimli bir şekilde aramak için sabit uzunluklu veri tipleri yardımcı olur. Bu özellikle tarih pulları ve hesap numaraları gibi yapılandırılmış veriler için geçerlidir. Önceden ne ile uğraştığınızı biliyorsanız, verimli dizinlere yüklemek daha kolaydır.

  2. Bütünlük ve kısıtlamalar. Sabit veri türlerine sahipse, verileri temiz tutmak kolaydır.

  3. Tarih. Bilgisayarlar birkaç megabayt RAM’e sahipken ve terabayt ölçekli depolama oldukça RDBMS’ler başlattı. Bir tablonun her satırına bir düzine bayt kaydetmek, bu şartlar altında binlerce dolar ve saatlerce zaman kazandırabilir.

  4. Müşteri tabanının laneti. Günümüzde RDBMS'ler çok karmaşık, en iyi duruma getirilmiş yazılım paketleridir ve onlarca yıldır veri toplamak için kullanılmaktadırlar. Olgunlar. Çalışırlar. Büyük ölçekli veri kaybına neden olan bir RDBMS çökmesi bugünlerde oldukça nadir görülür. Daha esnek bir veri yazma sistemine sahip bir şeye geçmek çoğu kurum için maliyet veya riske değmez.

Analoji: kentsel metro sistemlerinin daha dar bir ray mastarında daha iyi (daha sessiz, daha hızlı, daha verimli) çalışacağı açıkça görülebilir. Fakat bu gelişmeleri gerçekleştirmek için New York City metro sistemindeki tüm rayları nasıl değiştireceksiniz? Öyle değilsin, yani sahip olduklarını optimize ediyorsun.


3

Genel olarak, veritabanına ne depoladığınızla ilgili ne kadar ayrıntılı bilgi verirseniz, o diskle ne kadar yer ayıracağınız veya geri alırken ne kadar bellek ayıracağınız gibi bu verilerle ilgili çeşitli performans ölçümlerini optimize etmeye çalışabilir. .

Neden orta metin, uzun metin ve metin?

Hangi veritabanını kullandığınızdan emin değilim, bu yüzden tahmin etmek zorunda kalacağım: Bu veri türlerinden ikisinin, birinin bunlardan birinin üst sınırları olmadığını tahmin ediyorum. Üst sınırları olan metinler için veri türleri kullanmak, veritabanına her kayıt için ne kadar depolama alanına ihtiyaç duyacağını söyler. Bazı veritabanlarının büyük (muhtemelen sınırsız) metni ve küçük sabit uzunlukta metinleri kaydetmenin farklı yolları olabilir (bu, veritabanına göre değişebilir, sizinkileri görmek için el kitabınızı kontrol edin).

Neden ondalık, kayan nokta ve int?

Farklı hassasiyet seviyeleri, farklı miktarlarda depolama gerektirir ve her kullanım en yüksek derecede hassasiyet gerektirmez. Örneğin, buraya bakın: https://docs.oracle.com/cd/B28359_01/server.111/b28286/sql_elements001.htm#SQLRF50950

Oracle, farklı depolama gereksinimlerine ve hassasiyet seviyesi ve temsil edilebilecek sayıların boyutlarına göre farklı özelliklere sahip oldukça farklı tiplerde sayısal tiplere sahiptir.


2

Bir dereceye kadar tarihi.

Bir zamanlar, sekmeli veriler, belirli bir alanın her zaman aynı türde ve her kayıtta aynı yerde olması için önceden tanımlanmış alanlardan oluşan sabit uzunluklu kayıtlardan oluşan dosyalarda depolanır. Bu işlemeyi verimli hale getirdi ve kodlamanın karmaşıklığını sınırladı.

Böyle bir dosyaya bazı indeksler ekleyin ve ilişkisel bir veritabanının başlangıcına sahipsiniz.

İlişkisel veritabanları geliştikçe, değişken uzunluktaki metin veya ikili alanlar dahil olmak üzere daha fazla veri türü ve depolama seçeneği sunmaya başladılar. Ancak, bu değişken uzunluklu kayıtları başlattı ve sabit bir sapma ile kayıtları hesaplama veya alanlar aracılığıyla tutarlı bir şekilde bulma yeteneğini bozdu. Olursa olsun, makineler bugün eskisinden çok daha güçlü.

Bazen, bir miktar iş mantığının uygulanmasına yardımcı olmak için bir alan için belirli bir boyut belirlemek yararlı olabilir - Kuzey Amerika telefon numarası için 10 basamak söyleyin. Çoğu zaman bu sadece bir miktar hesaplama mirasıdır.


1

Bir veritabanı sabit boyutlu kayıtlar kullanıyorsa, veritabanındaki herhangi bir kayıt, içerikleri değiştirilse bile aynı yere sığmaya devam eder. Bunun aksine, bir veritabanı tam olarak alanları için gereken depolama alanını kullanarak kayıtları depolamaya çalışırsa, Emma Smith'in adını Emma Johnson olarak değiştirmek, kaydının mevcut konumuna sığmayacak kadar büyük olmasına neden olabilir. Kayıt yeterli odaya sahip bir yere taşınırsa, yerini izleyen herhangi bir dizin yeni konumu yansıtacak şekilde güncellenmesi gerekir.

Bu tür güncellemelerle ilişkili maliyeti düşürmenin çeşitli yolları vardır. Örneğin, sistem kayıt numaralarının ve veri konumlarının bir listesini tutarsa, bir kayıt hareket ederse güncellenmesi gereken tek şey bu liste olacaktır. Maalesef, bu tür yaklaşımlar hala önemli bir maliyete sahiptir (örneğin, kayıt numaraları ve konumlar arasında bir eşleştirmenin tutulması, kayıt alımının belirli bir kayıt numarası ile ilişkili verileri almak için ek bir adım gerektirmesini gerektirecektir). Sabit boyutlu kayıtların kullanılması verimsiz görünebilir, ancak işleri çok daha kolay hale getirir.


1

Bir web geliştiricisi olarak yaptığınız işlerin çoğu için, "başlık altında" neler olduğunu anlamanıza gerek yoktur. Ancak yardım ettiği zamanlar vardır.

Veritabanına “Bu sütuna yapılan girişlerde yalnızca 256 bayt düz metin verisi olacak” demesinin faydası nedir? veya "Bu sütun, 16.777.215 bayta kadar metin girişleri içerebilir"?

Şüphelendiğiniz gibi, sebep verimlilik ile yapmaktır. Soyutlamalar sızıyor . Gibi bir sorgu SELECT author FROM bookstablodaki tüm alanların boyutu bilindiğinde oldukça hızlı bir şekilde çalışabilir.

Joel'in dediği gibi

İlişkisel bir veritabanı nasıl uygulanır SELECT author FROM books? İlişkisel bir veritabanında, bir tablodaki her satır (örneğin, kitap tablosu) bayt cinsinden tam olarak aynı uzunluktadır ve her alan satırın başlangıcından itibaren her zaman sabit bir kayma değerindedir. Örneğin, kitaplar tablosundaki her kayıt 100 bayt uzunluğundaysa ve yazar alanı ofset 23 ise, o zaman bayt 23, 123, 223, 323, vb. Depolanan yazarlar vardır. Taşınacak kod nedir? Bu sorgu sonucu bir sonraki kayıt? Temel olarak, bu:

pointer += 100;

Bir CPU talimatı. Faaaaaaaaaast.

Çoğu zaman, umursamaya gerek duymadığın asfalt kumluklarından yeterince uzakta çalışıyorsun. Bir PHP tabanlı web geliştiricisi olarak , kodunuzun kaç CPU talimatı kullandığı ile ilgileniyor musunuz? Çoğu zaman, hayır, pek değil. Ancak bazen iki nedenden ötürü bilmek yararlı olur: kütüphanelerinizin verdiği kararları açıklayabilir; ve bazen kendi kodunuzda hızı dikkate almanız gerekir.

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.