Banyak kolom vs beberapa tabel - kinerja bijaksana

12

Ya, saya sadar bahwa normalisasi data harus menjadi prioritas saya (sebagaimana adanya).

  1. Aku punya tabel dengan 65 kolom menyimpan data kendaraan dengan kolom: used_vehicle, color, doors, mileage, pricedan sebagainya, total 65.
  2. Sekarang, saya bisa membagi itu dan memiliki Vehiclemeja, VehicleInterior, VehicleExterior, VehicleTechnical, VehicleExtra(semua satu-ke-satu dengan utama Vehicletabel).

Anggaplah saya akan memiliki sekitar 5 juta baris (kendaraan).

Aktif SELECTdengan WHEREklausa: Apakah kinerja akan lebih baik menelusuri (kedua kasus diindeks setidaknya pada IDs):

  1. Vehicle tabel dengan 65 kolom atau
  2. Vehicletabel dengan JOINSpada empat tabel lainnya (semua dengan 5 juta baris) untuk mengembalikan semua data yang terkait Vehicle?

(Sesuai mesin database, pertimbangkan PostgreSQL dan / atau MySQL).

Benar-benar menghargai wawasan terperinci yang mungkin Anda miliki dari pengalaman sebelumnya?

Urim Kurtishi
sumber
1
Salah satu alasan melakukan ini (partisi vertikal) adalah jika Anda memiliki kueri yang berhubungan dengan kolom dari VehicleInterior, kueri lain yang hanya menangani kolom dari VehicleTechnical, dll. Atau jika ada banyak baris / kendaraan yang sama sekali tidak memiliki info tentang (misalnya) VehicleExtrajadi alih-alih banyak baris dengan banyak nol di satu tabel, Anda memiliki baris di sisa tabel dan tidak ada baris diVehicleExtra
ypercubeᵀᴹ

Jawaban:

14

Dengan asumsi kita berbicara tentang hubungan 1: 1 di antara semua tabel.

Penyimpanan keseluruhan praktis selalu (jauh) lebih murah dengan satu tabel daripada beberapa tabel dalam hubungan 1: 1. Setiap baris memiliki 28 byte overhead, ditambah biasanya beberapa byte lagi untuk padding tambahan. Dan Anda perlu menyimpan kolom PK di setiap meja. Dan memiliki indeks terpisah (redundan) pada masing-masing kolom ini ... Ukuran tidak masalah untuk kinerja.

Ini bahkan benar jika banyak kolom NULL di sebagian besar baris karena penyimpanan NULL sangat murah :

Sementara mengambil semua kolom satu tabel secara substansial lebih cepat dari 5 tabel yang bergabung bersama. Ini juga jauh lebih sederhana . Lima tabel mungkin sulit untuk bergabung jika tidak semua baris ada di semua tabel. Dengan WHEREkondisi yang menargetkan satu tabel, cukup mudah untuk menambahkan tabel lain dengan LEFT JOIN. Tidak sepele jika Anda memiliki predikat pada beberapa tabel ...

Partisi vertikal masih dapat meningkatkan kinerja kueri tertentu. Misalnya, jika 90% kueri Anda mengambil 5 kolom yang sama dari 65 yang tersedia, ini akan lebih cepat dengan tabel hanya menahan 5 kolom ini.

OTOH, Anda mungkin dapat memenuhi permintaan tersebut pada beberapa kolom yang dipilih dengan indeks "penutup" yang memungkinkan pemindaian hanya indeks .

Kandidat lain untuk partisi vertikal: Jika Anda memiliki banyak pembaruan hanya pada beberapa kolom, sedangkan sisanya hampir tidak pernah berubah. Mungkin jauh lebih murah untuk membagi baris dalam kasus seperti itu, karena Postgres menulis versi baris baru untuk setiap pembaruan. Ada pengecualian untuk nilai besar yang disimpan di luar jalur ("TOASTed"). Keterangan lebih lanjut:

Itu benar-benar tergantung pada situasi lengkap. Jika ragu, gunakan solusi sederhana untuk memiliki satu meja, terutama jika itu menggambarkan kenyataan dengan baik: Dalam contoh Anda, itu semua adalah atribut mobil dan masuk akal bersama.

Erwin Brandstetter
sumber
pembaruan akan jarang terjadi jika tidak ada dan yang dipilih sebagian besar untuk semua kolom (halaman detail kendaraan) dan info utama (beberapa kolom) untuk daftar hasil pencarian, dan pada kenyataannya mungkin solusi terbaik adalah dua tabel: satu dengan info utama (beberapa kolom) ) dan tabel lainnya dengan sisa kolom. jadi dalam hal ini apa pendapat Anda tentang sql bergabung dengan katakanlah 5 juta baris - kinerja bijaksana? Terima kasih BTW atas upaya terperinci Anda
Urim Kurtishi
1
@octavius: Tabel tunggal dengan indeks multikolom pada beberapa kolom untuk memungkinkan pemindaian hanya indeks untuk daftar hasil mungkin merupakan rute terbaik. (Ketahuilah bahwa urutan kolom penting dalam indeks btree .) Gabungan tidak semahal itu, tetapi masih akan lebih cepat tanpa bergabung. Ukuran penyimpanan yang ditambahkan dan penyebaran data untuk beberapa tabel mungkin merupakan perlambatan yang lebih besar (lebih banyak halaman data untuk dibaca untuk setiap permintaan).
Erwin Brandstetter
1
Saya setuju dengan komentar Erwins bahwa jawabannya akan sangat bergantung pada situasi lengkap atau penggunaan dunia nyata. Jika Anda menemukan bahwa 90% dari kueri berada di subkumpulan kecil data dan kinerja benar-benar penting, maka mungkin ada alasan untuk membenarkan upaya ekstra tersebut dipecah menjadi banyak tabel. Secara pribadi saya akan mencoba untuk menjaga model data tetap sederhana. Juga, seberapa cepat cukup cepat? Berapa banyak upaya yang Anda lakukan untuk menyelamatkan milidetik terakhir? Sudahkah Anda mencoba membuat data apa pun dan melakukan tes apa pun?
Sir Swears-a-lot
@ ErwinBrandstetter yang Anda sebutkan dalam jawaban Anda bahwa hubungannya adalah 1: 1. Bagaimana dengan 1: N relasi kapal?
Langsing
Untuk relasi 1: N Anda membutuhkan dua tabel terpisah. Kecuali jika Anda menjejali banyak baris ke dalam array atau tipe dokumen. Maka itu tergantung. Prinsip-prinsip yang diuraikan di sini berlaku. Pola akses dan strategi indeks Anda dapat membuat perbedaan. Ajukan pertanyaan baru jika Anda ingin lebih spesifik.
Erwin Brandstetter
0

Pilih pada satu tabel harus selalu lebih cepat. Segera setelah Anda menemukan kendaraan Anda, Anda sudah memiliki semua detail.

Namun Anda kehilangan efisiensi normalisasi. Misalnya jika 1 mobil punya banyak model dengan opsi berbeda.

Apakah ini referensi db dari semua mobil? Atau daftar kendaraan bekas? Apakah akan ada banyak contoh model yang sama dengan opsi yang sama?

Sunting: saya harus memenuhi syarat jawaban saya sebagai rdbms umum daripada khusus postgres. Saya tunduk pada jawaban rinci @ Erwin khusus untuk postgres

Pak Bersumpah banyak
sumber
2
"Pilihan pada satu tabel harus selalu lebih cepat." Mengapa?
ypercubeᵀᴹ
Model kendaraan bermotor dan kendaraan bermotor adalah tabel yang berbeda, sehingga meja kendaraan memiliki kunci asing kendaraan model otomotif dan kendaraan bermotor. Saya tidak berpikir normalisasi adalah masalah di sini. saya mengerti bahwa memilih pada tabel tunggal akan lebih cepat, namun kami memiliki situasi yang berbeda, bagaimana baris dengan banyak kolom akan mempengaruhi kinerja dan sebagainya dibandingkan tabel dengan kolom yang lebih sedikit (tetapi beberapa tabel - 5 di antaranya bergabung)
Urim Kurtishi
Maaf saya telah melewatkan titik yang membuat dan model sudah terpisah. Versi singkatnya adalah bahwa bergabung mengambil upaya untuk mesin database. Jika Anda menggunakan satu tabel / baris, Anda akan mendapatkan semuanya dalam satu pilihan, yang akan menghasilkan lebih sedikit I / O dan overhead untuk mesin db.
Sir Swears-a-lot