SQL SELECT hız int ve varchar


110

Masa oluşturma sürecindeyim ve bu beni meraklandırdı.

Markası olan arabaları (fx BMW, Audi vb.) Saklarsam, markayı int veya varchar olarak saklarsam sorgu hızında herhangi bir fark yaratır mı?

Öyle

SELECT * FROM table WHERE make = 5 AND ...;

Daha hızlı / daha yavaş

SELECT * FROM table WHERE make = 'audi' AND ...;

yoksa hız aşağı yukarı aynı mı olacak?

Yanıtlar:


99

Int karşılaştırmaları varchar karşılaştırmalarından daha hızlıdır, çünkü ints varchars'tan çok daha az yer kaplar.

Bu hem indekslenmemiş hem de indeksli erişim için geçerlidir. Gitmenin en hızlı yolu dizine alınmış bir int sütunudur.


Postgreql sorusunu etiketlediğini gördüğüm gibi, farklı tarih türlerinin alan kullanımı ilginizi çekebilir:


13
7.4. Sayfaya atıfta bulunuyorsunuz. Modern versiyonlarda, 126 bayttan azsa, 1 bayt + uzunluk alırlar. Ayrıca, dizelerin çok daha yavaş olmasının nedeninin, genellikle harmanlamaya duyarlı karşılaştırmanın oldukça pahalı olması olduğunu unutmayın - dizenin daha fazla yer kaplaması değil. Ama sonuç elbette aynı.
Magnus Hagander

@Magnus - uyarı için teşekkürler. Yeterli tekrar puanınız olduğunu gördüğüm için cevabımı düzenlemekten çekinmeyin.
Robert Munteanu

"dize daha fazla yer kapladığından değil" ... minimum boyutların üzerindeki karakter dizileri, yüksek hassasiyetli sayılardan bile çok daha fazla yer kaplar, çünkü bir sayının (tekil) sabit bir birimi vardır, dizeler her zaman toplu türlerdir . Bir dizede karakter başına 4 bayt 64 bitlik sayı için 8 bayt, uzunluk baytı veya yapı dahil; veya inanılmaz derecede saf uygulamalar için başka bir sonlandırıcı karakter ...
MrMesees

@RobertMunteanu Hey Robert, özür dilerim, bunun eski bir gönderi olduğunu biliyorum, ancak aşağıdakileri kontrol edebilir miyim ... tamsayıları sorgulamak için, her dize sütununu başka bir tabloya (ilişki) bağlamam gerekiyor. ancak bu, her sorgu için daha fazla birleştirme işlemi gerektiği anlamına gelir. Bu değiş tokuşun buna değip değmediğini nasıl anlarım? Teşekkür ederim!
AiRiFiEd

2
"Int karşılaştırmaları varchar karşılaştırmalarından daha hızlıdır, çünkü intts varcharlardan çok daha az yer kaplar" - bu genel olarak doğru DEĞİLDİR . Kullandığınız DBMS'ye ve eklemek istediğiniz tam veri türlerine ve dizelerine bağlı olarak, (örneğin) 8 baytlık girişlerinizin ortalama uzunlukta 3-4 karakterlik bazı metin kimliklerini tutan ascii varchar'larından daha uzun olduğu ortaya çıkabilir. Dolayısıyla, bu cevap - kesin olmamak ve belirli bir bağlamdan veya deneysel sonuçlardan yoksun olmak - soruyu gerçekten cevaplamıyor. Herkes varcharların ints'ten çok daha fazla yer kaplamasına izin verildiğini bilir , ancak buna gerek YOKTUR.
Marcin Wojnarski

36

Bazı kaba kriterler:

Postgres 9.x'te 4 milyon kayıt

Table A = base table with some columns
Table B = Table A + extra column id of type bigint with random numbers
Table C = Table A + extra column id of type text with random 16-char ASCII strings

8 GB RAM, i7, SSD dizüstü bilgisayarda sonuçlar:

Size on disk:                A=261MB        B=292MB        C=322MB
Non-indexed by id: select count(*), select by id: 450ms same on all tables
Insert* one row per TX:       B=9ms/record        C=9ms/record
Bulk insert* in single TX:    B=140usec/record    C=180usec/record
Indexed by id, select by id:  B=about 200us       C=about 200us

* inserts to the table already containing 4M records

Bu nedenle, bu kurulum için, dizinleriniz RAM'e sığdığı sürece, bigint ve 16 karakterli metinler hızda bir fark yaratmaz.


6
Çok ilginç. Nasıl olur da fark önemsizdir?
Chibueze Opata

18

Varchar yerine int kullanmak biraz daha hızlı olacaktır. Hız için daha önemli olan, sorgunun kayıtları bulmak için kullanabileceği alanda bir dizine sahip olmaktır.

Bir int kullanmanın başka bir nedeni vardır ve bu da veritabanını normalleştirmektir. Tabloda 'Mercedes-Benz' metninin binlerce kez saklanması yerine, kimliğini saklamalı ve marka adını ayrı bir tabloda bir kez saklamalısınız.


Biraz daha açıklayabilir misin? Mercedes-BenzBinlerce kez kimliği saklamak yerine mi demek istiyorsun 1? Örneğin tablo car_brands, sütunlar Brandsve Id. Satır Mercedes-Benzve 1. Ve ana tablo sütununda Brandsve değerinde 1. Ve ne zaman SELECT, sonra ilk önce Idmasadan car_brandsve sonra SELECT Something FROM main_table WHERE Brands = (SELECT Id FROM car_brands WHERE Brands = Mercedes-Benz). Veya başka bir yaklaşım?
Andris

3
@ user2118559: Evet, onu böyle saklarsınız. Genellikle bir yerine bir alt sorgu daha katılmak kullanacağı verileri almak için: select something from main_table c inner join car_brands b on b.Id = c.Brands where b.Brands = 'Mercedes-Benz'.
Guffa

Neden olumsuz oy? Yanlış olduğunu düşündüğünüz şeyin ne olduğunu açıklamazsanız, cevabı iyileştiremez.
Guffa

8

Kayan olmayanlara karşı dizgi karşılaştırmasının gerçek performansına bakıldığında, bu durumda işaretsiz ve işaretli herhangi bir boyut önemli değildir. Boyut aslında performanstaki gerçek farktır. 1 bayt + (126 bayta kadar) ile 1,2,4 veya 8 bayt karşılaştırması ... açıkçası kayan olmayanlar dizelerden ve kayanlardan daha küçüktür ve dolayısıyla montajda daha CPU dostudur.

Tüm dillerde dizge-dizge karşılaştırması , CPU tarafından 1 komutta karşılaştırılabilecek bir şeyden daha yavaştır. 32 bit CPU'da 8 baytı (64 bit) karşılaştırmak bile bir VARCHAR (2) veya daha büyük bir işlemden daha hızlıdır. * Yine, üretilen derlemeye bakın (elle bile), karakter ile karakter karşılaştırmak için 1 ila 8 bayt CPU sayısal değerinden daha fazla talimat gerekir.

Şimdi, ne kadar hızlı? ayrıca veri hacmine de bağlıdır. Sadece 5'i 'audi' ile karşılaştırıyorsanız - ve DB'nizin sahip olduğu tek şey buysa, ortaya çıkan fark o kadar küçüktür ki, onu asla göremezsiniz. İşlemciye, uygulamaya (istemci / sunucu, web / komut dosyası, vb.) Bağlı olarak, DB sunucusunda birkaç yüz karşılaştırmaya (belki de fark edilmeden önce belki birkaç bin karşılaştırma) ulaşana kadar görmeyeceksiniz.

  • Hash karşılaştırmalarıyla ilgili yanlış anlaşmazlığı ortadan kaldırmak için. Çoğu karma algoritmanın kendisi yavaştır, bu nedenle CRC64 ve daha küçük şeylerden yararlanamazsınız. 12 yıldan fazla bir süredir, çok ülkeli arama motorları için arama algoritmaları ve kredi büroları için 7 yıl geliştirdim. Sayısal olarak daha hızlı tutabileceğiniz her şey ... örneğin telefon numaraları, posta kodları, hatta para birimi * 1000 (depolama) para birimi div 1000 (alma), karşılaştırmalar için DECIMAL'den daha hızlıdır.

Ozz


6

İndeks olsun veya olmasın, int çok daha hızlıdır (varchar ne kadar uzunsa, o kadar yavaş olur).

Başka bir neden: varchar alanındaki dizin, int'den çok daha büyük olacaktır. Daha büyük tablolar için bu, yüzlerce megabayt (ve binlerce sayfa) anlamına gelebilir. Bu, performansı çok daha kötü hale getirir çünkü tek başına dizini okumak birçok disk okuması gerektirir.


3
Örneğin 5 milyon "audi" kaydı söz konusu olduğunda, dizin yalnızca "audi" dizesinin yalnızca bir kopyasını ve birincil_anahtarın 5 milyon tamsayısını tutmaz mı? Boyut farkı gerçekten o kadar büyük olur muydu, vchar veya tam sayı olabilir mi?
lulalala

Haklısın lulalala ama rastgele dizeler içerecek bir sütun için cevap yeterince adil.
Awais fiaz

4

Genelde int daha hızlı olacaktır. Varchar ne kadar uzun olursa o kadar yavaşlar


3

İpucu: alanına yönelik olası değerler ise marka olacak asla (veya nadiren) değişim, bir uzlaşma olarak enum kullanabilirsiniz. İyi hızı iyi okunabilirlikle birleştirir.


1
İlginç, ENUM ve int arasındaki hız farkı nasıl olacak?
googletorp

PostgresSQL'in bir enumveri türü var mı? MySQL'e özgü olduğunu düşündüm.
Robert Munteanu

Postgres'te ENUM var, ancak MySQL ile tamamen aynı şekilde uygulandığını düşünmüyorum. postgresql.org/docs/current/static/datatype-enum.html
googletorp

2
Performans açısından, ENUM, arama alanındaki int ile aşağı yukarı aynı, ancak hedef listedeki varchar olarak performans göstermelidir (çünkü yalnızca int değil, eşleşen satırlar için tüm dizeyi istemciye aktarmak zorundadır)
Magnus Hagander

1
İşte MySQL'de neden enum KULLANILMAMASI gerektiğine dair ilginç bir okuma (sadece ateşe biraz yakıt eklemek için: D)
Wilt

1

Alanlardan herhangi birinde indekslemeyi açarsanız, daha hızlı olacaktır. Sorunuza gelince, bence intdaha hızlı varchar.


0

Biraz akraba. Evet, INT'ler daha hızlı olacak, ancak soru, sizin durumunuzda fark edilebilir olup olmadığıdır. VARCHAR'lar sadece küçük kelimeler mi yoksa daha uzun metinler mi? ve tabloda kaç satır var? Yalnızca birkaç satır varsa, büyük olasılıkla tamamen bellekte arabelleğe alınacaktır (sıklıkla istendiğinde), bu durumda çok fazla fark görmeyeceksiniz. Sonra tabiki tablo büyüdükçe daha da önem kazanan indeksleme var. SSD'leri kullanmak, optimize edilmiş sorgularla HD'lerden daha hızlı olabilir. Ayrıca iyi disk denetleyicileri bazen sorguları> 10 kat hızlandırır. Bu, sorguları okumayı ve yazmayı kolaylaştıran (karmaşık birleştirmeler yazmaya gerek kalmadan) ve geliştirmeyi hızlandıran VARCHAR'ları kullanmaya yer bırakabilir. Ancak, püristler aynı fikirde olmayacak ve her zaman her şeyi normalleştirecektir.

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.