Pertanyaan Mengapa bergabung buruk ketika mempertimbangkan skalabilitas?


Mengapa bergabung buruk atau 'lambat'. Saya tahu saya mendengar ini lebih dari sekali. Saya menemukan kutipan ini

Masalahnya adalah bergabung relatif   lambat, terutama atas data yang sangat besar   set, dan jika mereka memperlambat Anda   situs web lambat. Butuh waktu lama   untuk mendapatkan semua bagian yang terpisah   informasi dari disk dan menempatkan semuanya   bersama lagi.

sumber

Saya selalu berpikir mereka cepat terutama ketika mencari PK. Kenapa mereka 'lambat'?


76
2018-04-12 17:02


asal


Jawaban:


Bergabung dengan dua sumber data terpisah relatif lambat, setidaknya dibandingkan dengan tidak bergabung dengan mereka. Tetapi ingat bahwa alternatifnya adalah tidak lagi memiliki dua bagian data yang terpisah sama sekali; Anda harus meletakkan dua titik data yang berbeda dalam catatan yang sama. Anda tidak dapat menggabungkan dua bagian data yang berbeda tanpa ada konsekuensi di suatu tempat, jadi pastikan Anda memahami trade-off.

Kabar baiknya adalah bahwa database relasional modern baik di bergabung. Anda tidak harus berpikir untuk bergabung dengan lambat dengan database yang bagus. Basis data menyediakan sejumlah cara untuk mengambil gabungan baku dan membuatnya banyak lebih cepat:

  • Bergabung dengan kunci pengganti (kolom autonumer / identitas) daripada kunci alami. Ini berarti perbandingan yang lebih kecil (dan karenanya lebih cepat) selama operasi gabungan
  • Indeks
  • Tampilan terwujud / diindeks (anggap ini sebagai gabungan yang telah dihitung sebelumnya atau berhasil de-normalisasi)
  • Kolom yang dihitung. Anda dapat menggunakan ini untuk hash atau jika tidak pra-menghitung kolom kunci dari sebuah gabung, sehingga apa yang akan menjadi perbandingan rumit untuk bergabung sekarang jauh lebih kecil dan berpotensi pra-indeks.
  • Partisi tabel (membantu dengan set data besar dengan menyebarkan beban ke beberapa disk, atau membatasi apa yang mungkin menjadi scan tabel ke scan partisi)
  • OLAP (pra-menghitung hasil dari jenis-jenis pertanyaan / gabungan tertentu. Ini tidak sepenuhnya benar, tetapi Anda dapat menganggap ini sebagai umum denormalization)

Saya akan pergi sejauh mengatakan itu alasan utama database relasional ada sama sekali adalah untuk memungkinkan Anda bergabung secara efisien*. Ini tentu tidak hanya untuk menyimpan data terstruktur (Anda bisa melakukannya dengan konstruksi file datar seperti csv atau xml). Beberapa opsi yang saya cantumkan bahkan akan membiarkan Anda sepenuhnya membangun join Anda terlebih dahulu, jadi hasilnya sudah dilakukan sebelum Anda mengeluarkan query - sama seperti jika Anda telah melakukan denormalized data (diakui pada biaya operasi penulisan lebih lambat).

Jika Anda memiliki gabungan lambat, Anda mungkin tidak menggunakan database Anda dengan benar. 

De-normalisasi harus dilakukan hanya setelah teknik-teknik lain ini gagal. Dan satu-satunya cara Anda benar-benar dapat menilai "kegagalan" adalah menetapkan tujuan kinerja yang berarti dan mengukur terhadap tujuan tersebut. Jika Anda belum mengukurnya, terlalu dini untuk berpikir tentang de-normalisasi.

* Artinya, ada sebagai entitas yang berbeda dari koleksi tabel belaka. Alasan tambahan untuk rdbms nyata adalah akses bersamaan yang aman.


76
2018-04-12 17:23



Bergabung bisa lebih lambat daripada menghindari mereka melalui de-normalisasi tetapi jika digunakan dengan benar (bergabung di kolom dengan indeks yang tepat dan seterusnya) mereka tidak secara inheren lambat.

De-normalisasi adalah salah satu dari banyak teknik pengoptimalan yang dapat Anda pertimbangkan jika skema database yang dirancang dengan baik menunjukkan masalah kinerja.


28
2018-04-12 17:11



artikel mengatakan bahwa mereka lambat bila dibandingkan dengan tidak adanya bergabung. ini dapat dicapai dengan denormalization. jadi ada trade off antara kecepatan dan normalisasi. jangan lupa tentang pengoptimalan prematur juga :)


12
2018-04-12 17:08



Pertama-tama, raison d'etre database relasional (alasan untuk menjadi) adalah untuk dapat memodelkan hubungan antar entitas. Bergabung hanya mekanisme yang kita lalui hubungan tersebut. Mereka pasti datang dengan biaya nominal, tetapi tanpa bergabung, tidak ada alasan untuk memiliki database relasional.

Di dunia akademis kita belajar hal-hal seperti berbagai bentuk normal (1st, 2nd, 3rd, Boyce-Codd, dll.), Dan kita belajar tentang berbagai jenis kunci (primer, asing, alternatif, unik, dll.) Dan bagaimana hal-hal ini cocok untuk merancang basis data. Dan kami mempelajari dasar-dasar SQL serta memanipulasi struktur dan data (DDL & DML).

Di dunia korporat, banyak dari konstruk akademis berubah menjadi jauh kurang kuat daripada yang kita percayai. Contoh sempurna adalah gagasan kunci primer. Secara akademis itu adalah atribut (atau kumpulan atribut) yang secara unik mengidentifikasi satu baris dalam tabel. Jadi dalam banyak masalah domain, kunci primer akademik yang tepat adalah gabungan dari 3 atau 4 atribut. Namun, hampir semua orang di dunia perusahaan modern menggunakan integer sekuensial yang dihasilkan secara otomatis sebagai kunci utama tabel. Mengapa? Ada dua alasan. Yang pertama adalah karena membuat model lebih bersih ketika Anda memigrasi FK di semua tempat. Yang kedua, dan paling erat untuk pertanyaan ini, adalah bahwa mengambil data melalui gabungan lebih cepat dan lebih efisien pada satu bilangan bulat daripada pada 4 kolom varchar (sebagaimana telah disebutkan oleh beberapa orang).

Mari kita gali lebih dalam sekarang ke dalam dua subtipe khusus dari basis data dunia nyata. Tipe pertama adalah database transaksional. Ini adalah dasar untuk banyak aplikasi e-commerce atau manajemen konten yang menggerakkan situs modern. Dengan DB transaksi, Anda sangat mengoptimalkan "throughput transaksi". Sebagian besar aplikasi perdagangan atau konten harus menyeimbangkan kinerja kueri (dari tabel tertentu) dengan kinerja sisipan (di tabel lain), meskipun masing-masing aplikasi memiliki masalah yang digerakkan oleh bisnis unik untuk dipecahkan.

Tipe kedua dari database dunia nyata adalah database pelaporan. Ini digunakan hampir secara eksklusif untuk mengumpulkan data bisnis dan untuk menghasilkan laporan bisnis yang berarti. Mereka biasanya dibentuk berbeda dari database transaksi di mana data dihasilkan dan mereka sangat dioptimalkan untuk kecepatan pemuatan data massal (ETLs) dan kinerja query dengan kumpulan data besar atau kompleks.

Dalam setiap kasus, pengembang atau DBA harus hati-hati menyeimbangkan fungsi dan kurva kinerja, dan ada banyak trik peningkatan kinerja di kedua sisi persamaan. Di Oracle, Anda dapat melakukan apa yang disebut "menjelaskan rencana" sehingga Anda dapat melihat secara khusus bagaimana kueri diurai dan dijalankan. Anda ingin memaksimalkan penggunaan indeks DB yang tepat. Satu yang benar-benar jahat tidak-tidak adalah meletakkan fungsi di mana klausa kueri. Setiap kali Anda melakukan itu, Anda menjamin bahwa Oracle tidak akan menggunakan indeks pada kolom tertentu dan Anda mungkin akan melihat scan tabel penuh atau parsial dalam rencana menjelaskan. Itu hanya satu contoh spesifik tentang bagaimana sebuah query bisa ditulis yang akhirnya menjadi lambat, dan itu tidak ada hubungannya dengan bergabung.

Dan sementara kita berbicara tentang scan tabel, mereka jelas mempengaruhi kecepatan query secara proporsional dengan ukuran tabel. Scan tabel penuh dari 100 baris bahkan tidak terlihat. Jalankan permintaan yang sama di atas meja dengan 100 juta baris, dan Anda harus kembali minggu depan untuk kembali.

Mari kita bicara tentang normalisasi sebentar. Ini adalah topik akademis lain yang sangat positif yang bisa terlalu ditekankan. Sebagian besar waktu ketika kita berbicara tentang normalisasi kita benar-benar berarti penghapusan data duplikat dengan memasukkannya ke dalam tabelnya sendiri dan migrasi seorang FK. Orang-orang biasanya melewatkan seluruh ketergantungan yang dijelaskan oleh 2NF dan 3NF. Namun dalam kasus ekstrim, tentu saja mungkin untuk memiliki database BCNF yang sempurna yang sangat besar dan binatang lengkap untuk menulis kode melawan karena itu sangat dinormalisasi.

Jadi, di mana kita menyeimbangkan? Tidak ada satu pun jawaban terbaik. Semua jawaban yang lebih baik cenderung menjadi kompromi antara kemudahan pemeliharaan struktur, kemudahan pemeliharaan data dan kemudahan pembuatan kode / pemeliharaan. Secara umum, semakin sedikit duplikasi data, semakin baik.

Jadi mengapa bergabung terkadang lambat? Kadang-kadang desain relasional yang buruk. Terkadang pengindeksan tidak efektif. Terkadang ini masalah volume data. Kadang-kadang itu adalah permintaan yang ditulis secara mengerikan.

Maaf untuk jawaban yang bertele-tele, tapi saya merasa terdorong untuk memberikan konteks yang lebih menyenangkan di sekitar komentar saya daripada hanya mengeluarkan jawaban 4-peluru.


10
2018-04-13 01:00



Orang-orang dengan database berukuran terrabyte masih menggunakan gabungan, jika mereka dapat membuatnya bekerja dengan kinerja yang bijaksana maka Anda juga bisa.

Ada banyak alasan untuk tidak melakukan denominasi. Pertama, kecepatan kueri pemilihan bukan satu-satunya atau bahkan masalah utama dengan basis data. Integritas data adalah perhatian pertama. Jika Anda denormalize maka Anda harus menempatkan teknik untuk menyimpan data denormalized sebagai perubahan data induk. Jadi misalkan Anda mengambil untuk menyimpan nama klien di semua tabel daripada bergabung ke tabel klien di client_Id. Sekarang ketika nama klien berubah (100% kemungkinan beberapa nama klien akan berubah seiring waktu), sekarang Anda perlu memperbarui semua catatan anak untuk mencerminkan perubahan itu. Jika Anda melakukan ini pemutakhiran kaskade dan Anda memiliki satu juta catatan anak, seberapa cepat Anda kira akan terjadi dan berapa banyak pengguna yang akan mengalami masalah penguncian dan penundaan dalam pekerjaan mereka sementara itu terjadi? Lebih lanjut, kebanyakan orang yang melakukan denormalisasi karena "bergabung lambat" tidak cukup tahu tentang database untuk memastikan integritas data mereka terlindungi dan sering berakhir dengan database yang memiliki data yang tidak dapat digunakan karena integritasnya sangat buruk.

Denormalization adalah proses kompleks yang membutuhkan pemahaman menyeluruh tentang kinerja dan integritas basis data jika harus dilakukan dengan benar. Jangan mencoba melakukan denormalisasi kecuali Anda memiliki keahlian seperti itu pada staf.

Bergabung cukup cepat jika Anda melakukan beberapa hal. Pertama-tama gunakan kunci suggorgate, sebuah int bergabung hampir hampir menjadi yang tercepat bergabung. Kedua selalu indeks kunci asing. Gunakan tabel turunan atau gabungkan ketentuan untuk membuat kumpulan data yang lebih kecil untuk difilter. Jika Anda memiliki database yang sangat kompleks, maka rekrutlah orang basis data profesional dengan pengalaman dalam membagi dan mengelola basis data besar. Ada banyak teknik untuk meningkatkan kinerja tanpa menyingkirkan gabungan.

Jika Anda hanya perlu kemampuan query, maka ya Anda dapat mendesain datawarehouse yang dapat denormalized dan dihuni melalui alat ETL (dioptimalkan untuk kecepatan) bukan entri data pengguna.


9
2018-04-12 17:44



Bergabung lambat jika

  • data tidak diindeks dengan benar
  • hasil buruk disaring
  • bergabung dengan kueri yang ditulis dengan buruk
  • set data yang sangat besar dan kompleks

Jadi, benar, semakin besar data Anda mengatur semakin banyak pemrosesan yang Anda perlukan untuk kueri tetapi memeriksa dan mengerjakan tiga opsi pertama di atas akan sering menghasilkan hasil yang bagus.

Sumber Anda memberikan denormalization sebagai opsi. Ini baik-baik saja selama Anda sudah kehabisan alternatif yang lebih baik.


8
2018-04-12 17:13



Sambungan bisa lambat jika sebagian besar rekaman dari setiap sisi perlu dipindai.

Seperti ini:

SELECT  SUM(transaction)
FROM    customers
JOIN    accounts
ON      account_customer = customer_id

Bahkan jika indeks didefinisikan account_customer, semua catatan dari yang terakhir masih perlu dipindai.

Untuk daftar permintaan ini, pengoptimal yang layak bahkan tidak akan mempertimbangkan jalur akses indeks, melakukan HASH JOIN atau a MERGE JOIN sebagai gantinya.

Perhatikan bahwa untuk permintaan seperti ini:

SELECT  SUM(transaction)
FROM    customers
JOIN    accounts
ON      account_customer = customer_id
WHERE   customer_last_name = 'Stellphlug'

bergabung akan sangat mungkin akan cepat: pertama, indeks pada customer_last_name akan digunakan untuk memfilter semua Stellphlug's (yang tentu saja, tidak terlalu banyak), kemudian scan indeks account_customer akan dikeluarkan untuk setiap Stellphlug untuk menemukan transaksinya.

Terlepas dari kenyataan bahwa ini dapat menjadi miliaran catatan di accounts dan customers, hanya sedikit yang benar-benar perlu dipindai.


7
2018-04-12 17:07