SQL SELECT kecepatan int vs varchar

110

Saya sedang dalam proses membuat tabel dan itu membuat saya bertanya-tanya.

Jika saya menyimpan, katakanlah mobil yang memiliki merek (fx BMW, Audi dll.), Apakah itu akan membuat perbedaan pada kecepatan kueri jika saya menyimpan merek sebagai int atau varchar.

Begitu juga

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

Lebih cepat / lebih lambat dari

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

atau akankah kecepatannya kurang lebih sama?

googletorp
sumber

Jawaban:

99

Perbandingan int lebih cepat daripada perbandingan varchar, untuk fakta sederhananya bahwa int memakan lebih sedikit ruang daripada varchar.

Ini berlaku baik untuk akses yang tidak diindeks maupun yang diindeks. Cara tercepat untuk pergi adalah kolom int yang diindeks.


Seperti yang saya lihat, Anda telah menandai pertanyaan postgreql, Anda mungkin tertarik dengan penggunaan spasi dari tipe tanggal yang berbeda:

Robert Munteanu
sumber
13
Anda mengacu pada halaman 7.4. Dalam versi modern, mereka membutuhkan panjang 1byte + jika Anda memiliki <126 byte. Perhatikan juga bahwa alasan string jauh lebih lambat sering kali karena perbandingan peka-pemeriksaan sangat mahal - bukan karena string membutuhkan lebih banyak ruang. Tapi hasil akhirnya sama, tentunya.
Magnus Hagander
@ Magnus - terima kasih atas perhatiannya. Jangan ragu untuk mengedit jawaban saya karena saya melihat Anda memiliki poin repetisi yang cukup.
Robert Munteanu
"bukan berarti string membutuhkan lebih banyak ruang" ... string karakter di atas ukuran minimal membutuhkan lebih banyak ruang daripada angka presisi tinggi, karena angka (tunggal) memiliki unit tetap, string selalu merupakan jenis agregat . 8 byte untuk 64-bit nomor 4 byte per karakter dalam sebuah string, termasuk baik byte panjang atau struct; atau karakter terminator lain untuk implementasi yang sangat naif ...
MrMesees
@RobertMunteanu Hai Robert, maaf saya tahu ini adalah posting lama tetapi dapatkah saya dengan ramah memeriksa ... berikut ini: untuk query integer, saya harus menghubungkan setiap kolom string ke tabel lain (hubungan). namun, itu berarti lebih banyak operasi penggabungan diperlukan untuk setiap kueri. Bagaimana cara saya menentukan apakah trade-off ini sepadan? Terima kasih!
AiRiFiEd
2
"Perbandingan int lebih cepat daripada perbandingan varchar, karena fakta sederhana bahwa int mengambil lebih sedikit ruang daripada varchar" - ini TIDAK benar secara umum . Bergantung pada DBMS yang Anda gunakan dan tipe data dan string yang ingin Anda masukkan, mungkin ternyata int 8-byte Anda (katakanlah) lebih panjang daripada ascii varchars yang memiliki beberapa ID tekstual dengan panjang rata-rata 3-4 karakter. Jadi, jawaban ini - karena tidak tepat dan tidak memiliki konteks khusus atau hasil eksperimen - tidak benar-benar menjawab pertanyaan tersebut. Semua orang tahu bahwa varchars diizinkan untuk mengambil lebih banyak ruang daripada int, tetapi mereka TIDAK harus melakukannya.
Marcin Wojnarski
36

Beberapa tolok ukur kasar:

4 juta catatan di Postgres 9.x

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

Hasil pada RAM 8GB, i7, laptop SSD:

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

jadi sepertinya untuk pengaturan ini, selama indeks Anda sesuai dengan RAM, teks bigint vs 16 karakter tidak membuat perbedaan kecepatan.

Grzegorz Luczywo
sumber
6
Sangat menarik. Kenapa perbedaannya bisa diabaikan?
Chibueze Opata
18

Ini akan menjadi sedikit lebih cepat menggunakan int daripada varchar. Yang lebih penting untuk kecepatan adalah memiliki indeks di bidang yang dapat digunakan kueri untuk menemukan rekaman.

Ada alasan lain untuk menggunakan int, dan itu adalah untuk menormalkan database. Alih-alih menyimpan teks 'Mercedes-Benz' ribuan kali di tabel, Anda harus menyimpan id-nya dan menyimpan nama mereknya sekali dalam tabel terpisah.

Guffa
sumber
Bisakah Anda menjelaskan lebih lanjut? Apakah maksud Anda bukannya Mercedes-Benzmenyimpan ribuan kali id 1. Misalnya tabel car_brands, kolom Brandsdan Id. Baris Mercedes-Benzdan 1. Dan di kolom tabel utama Brandsdan nilai 1. Dan ketika SELECT, maka pada awalnya mendapatkan Iddari meja car_brandsdan kemudian SELECT Something FROM main_table WHERE Brands = (SELECT Id FROM car_brands WHERE Brands = Mercedes-Benz). Atau pendekatan lain?
Andris
3
@ user2118559: Ya, begitulah cara Anda menyimpannya. Untuk mendapatkan data yang Anda biasanya akan menggunakan join daripada subquery: select something from main_table c inner join car_brands b on b.Id = c.Brands where b.Brands = 'Mercedes-Benz'.
Guffa
Mengapa suara negatifnya? Jika Anda tidak menjelaskan apa yang menurut Anda salah, itu tidak dapat memperbaiki jawabannya.
Guffa
8

Menguraikan kinerja sebenarnya dari perbandingan string versus non-float, dalam hal ini ukuran apa pun yang tidak ditandatangani dan ditandatangani tidak menjadi masalah. Ukuran sebenarnya adalah perbedaan kinerja yang sebenarnya. Baik itu perbandingan 1byte + (hingga 126bytes) versus 1,2,4 atau 8 byte ... jelas non-float lebih kecil dari string dan float, dan dengan demikian lebih ramah CPU dalam perakitan.

Perbandingan string ke string dalam semua bahasa lebih lambat daripada sesuatu yang dapat dibandingkan dalam 1 instruksi oleh CPU. Bahkan membandingkan 8 byte (64bit) pada CPU 32bit masih lebih cepat daripada VARCHAR (2) atau lebih besar. * Sekali lagi, lihat perakitan yang dihasilkan (bahkan dengan tangan) dibutuhkan lebih banyak instruksi untuk membandingkan karakter demi karakter daripada 1 hingga 8 byte CPU numerik.

Sekarang, seberapa cepat? tergantung juga pada volume data. Jika Anda hanya membandingkan 5 dengan 'audi' - dan hanya itu yang dimiliki DB Anda, perbedaan yang dihasilkan sangat minim sehingga Anda tidak akan pernah melihatnya. Tergantung pada CPU, implementasi (klien / server, web / script, dll) Anda mungkin tidak akan melihatnya sampai Anda mencapai beberapa ratus perbandingan pada server DB (bahkan mungkin beberapa ribu perbandingan sebelum terlihat).

  • Untuk membatalkan sengketa yang salah tentang perbandingan hash. Sebagian besar algoritma hashing sendiri lambat, jadi Anda tidak mendapatkan keuntungan dari hal-hal seperti CRC64 dan yang lebih kecil. Selama lebih dari 12 tahun saya mengembangkan algoritme penelusuran untuk mesin telusur multi-county dan 7 tahun untuk biro kredit. Apa saja yang dapat Anda simpan dalam numerik lebih cepat ... misalnya nomor telepon, kode pos, bahkan mata uang * 1000 (penyimpanan) mata uang div 1000 (pengambilan) lebih cepat daripada DECIMAL untuk perbandingan.

Ozz

Ozz Nixon
sumber
6

Indeks atau tidak, int jauh lebih cepat (semakin lama varchar, semakin lambat itu).

Alasan lain: indeks di bidang varchar akan jauh lebih besar daripada di int. Untuk tabel yang lebih besar mungkin berarti ratusan megabyte (dan ribuan halaman). Itu membuat kinerja jauh lebih buruk karena membaca indeks saja membutuhkan banyak pembacaan disk.

Konrad Garus
sumber
3
Misalnya dari 5 juta record "audi", bukankah indeks hanya akan menyimpan satu salinan string "audi" dan 5 juta integer primary_key? Apakah perbedaan ukuran benar-benar sebesar itu, baik itu vchar atau integer?
lulalala
Anda benar lulalala tetapi untuk kolom yang akan berisi string acak jawabannya cukup adil.
Awais fiaz
4

Secara umum int akan lebih cepat. Semakin lama varchar semakin lambat

anthares
sumber
3

Petunjuk: Jika nilai yang mungkin untuk field make tidak akan pernah (atau jarang) berubah, Anda dapat menggunakan ENUM sebagai kompromi. Ini menggabungkan kecepatan yang baik dengan keterbacaan yang baik.

Thomas Schaub
sumber
1
Menarik, Bagaimana perbedaan kecepatan antara ENUM dan int?
googletorp
Apakah PostgresSQL memiliki enumtipe data? Saya pikir itu khusus MySQL.
Robert Munteanu
Postgres memiliki ENUM, tetapi saya rasa ini tidak diimplementasikan dengan cara yang sama seperti MySQL. postgresql.org/docs/current/static/datatype-enum.html
googletorp
2
Dari segi kinerja, ENUM harus melakukan kurang lebih sama seperti int di bidang pencarian, tetapi sebagai varchar dalam daftar target (karena harus mentransfer seluruh string ke klien untuk baris yang cocok, bukan hanya int)
Magnus Hagander
1
Berikut bacaan menarik tentang mengapa TIDAK menggunakan enum di MySQL (hanya untuk menambahkan beberapa bahan bakar ke api: D)
Wilt
1

Jika Anda mengaktifkan pengindeksan di salah satu bidang, ini akan lebih cepat. Adapun pertanyaan Anda, saya pikir intlebih cepat dari varchar.

Sarfraz
sumber
0

Agak relatif. Ya, INT akan lebih cepat, tetapi pertanyaannya adalah apakah itu terlihat dalam situasi Anda. Apakah VARCHAR hanya berupa kata-kata kecil, atau teks yang lebih panjang? dan berapa baris di tabel? Jika hanya ada beberapa baris, kemungkinan besar akan sepenuhnya di-buffer di memori (jika sering diminta), dalam hal ini Anda tidak akan melihat banyak perbedaan. Lalu tentu saja ada pengindeksan, yang menjadi lebih penting saat tabel tumbuh. Menggunakan SSD mungkin lebih cepat daripada HD dengan kueri yang dioptimalkan. Juga pengontrol disk yang baik terkadang mempercepat kueri> 10x. Ini mungkin menyisakan ruang untuk hanya menggunakan VARCHAR yang membuat kueri membaca dan menulis lebih mudah (tidak perlu menulis gabungan yang rumit) dan mempercepat pengembangan. Namun kaum Puritan tidak akan setuju dan selalu menormalkan segalanya.

Alex
sumber