Bergabung untuk orang malas?


169

Saya baru-baru ini berdiskusi dengan pengembang lain yang mengklaim kepada saya bahwa GABUNGAN (SQL) tidak berguna. Secara teknis ini benar tetapi ia menambahkan bahwa menggunakan gabungan kurang efisien daripada membuat beberapa permintaan dan tabel tautan dalam kode (C # atau Java).

Baginya bergabung adalah untuk orang-orang malas yang tidak peduli dengan kinerja. Apakah ini benar? Haruskah kita menghindari menggunakan gabungan?


114
Tidak. Basis data dioptimalkan untuk melakukan penggabungan, mereka sangat cepat terutama untuk kumpulan data besar. Anda tidak ingin aplikasi Anda memuat puluhan ribu baris dan menggabungkannya secara manual.
halfdan

91
Bahasa pemrograman adalah untuk orang malas; mereka kurang efisien daripada mengkode instruksi CPU dengan tangan. :)
Michael McGowan

76
Apa nama pengembangnya? Saya ingin memastikan saya tidak pernah mempekerjakannya.
Joe

39
@Michael meh, programmer nyata menggunakan kupu-kupu ...
Marc Gravell

14
Apakah Anda "ini benar" - tidak, tidak. Basis data bekerja melalui teori himpunan; bergabung dengan set bekerja dengan sangat baik dan bermanfaat ...
Marc Gravell

Jawaban:


188

Tidak, kita harus menghindari pengembang yang memiliki pendapat yang sangat salah.

Dalam banyak kasus, penggabungan basis data adalah beberapa urutan besarnya lebih cepat dari apa pun yang dilakukan melalui klien, karena penggabungan DB pulang pergi, dan DB dapat menggunakan indeks untuk melakukan penggabungan.

Dari atas kepala saya, saya bahkan tidak bisa membayangkan satu skenario di mana bergabung dengan benar akan lebih lambat daripada operasi sisi klien yang setara.

Sunting: Ada beberapa kasus yang jarang terjadi di mana kode klien kustom dapat melakukan hal-hal lebih efisien daripada DB langsung bergabung (lihat komentar oleh meriton). Tapi ini sangat pengecualian.


1
Bagaimana dengan gabungan 3 arah? Tidakkah ada kasus di mana Anda sebaiknya melakukannya "dalam kode"?
julien_c

56
Bergabung dengan server aplikasi bisa lebih efisien jika bergabung di database menyebabkan redundansi parah pada set hasil yang dikirim melalui jaringan. Pertimbangkan tabel A dan B, di mana setiap baris dalam A dikaitkan dengan 20 baris di B, B hanya memiliki 100 baris, dan kami ingin mengambil 1000 baris pertama dari A dengan baris terkait dari B. Bergabung dalam database akan menghasilkan 20 * 1000 tupel dikirim melalui jaringan. Jika bergabung dilakukan di server aplikasi (pertama mengambil seluruh tabel B ke dalam memori), hanya 100 + 1000 baris dikirim di seluruh jaringan.
meriton

7
Namun, Anda tentu benar bahwa bergabung dalam database jauh lebih cepat dalam banyak kasus, dan karena itu bukan hanya masalah kenyamanan, tetapi kebutuhan.
meriton

13
Saya sudah cukup beruntung untuk berbicara dengan beberapa pengembang yang bekerja pada SQL Server di Microsoft. Ini akan membuat Anda pusing mendengar optimisasi yang mereka lakukan pada kueri. Siapa pun yang berpikir bahwa mereka lebih pintar dari itu perlu ditampar.
riwalk

2
@meriton saya sedikit terkejut; Saya berharap perpustakaan klien untuk mengoptimalkan gabungan silang.
Phil Lello

83

Kedengarannya bagi saya seperti rekan Anda akan melakukannya dengan baik dengan database-dokumen no-sql atau toko kunci-nilai. Alat itu sendiri sangat bagus dan cocok untuk banyak masalah.

Namun, relasional database sangat dioptimalkan untuk bekerja dengan set. Ada banyak, banyak cara untuk menanyakan data berdasarkan gabungan yang jauh lebih efisien daripada banyak perjalanan pulang-pergi. Di sinilah serbaguna rdbms berasal. Anda dapat mencapai hal yang sama di toko nosql juga, tetapi Anda sering berakhir dengan membangun struktur terpisah yang cocok untuk setiap sifat kueri yang berbeda.

Singkatnya: Saya tidak setuju. Dalam RDBMS, gabungan merupakan hal mendasar . Jika Anda tidak menggunakannya, Anda tidak menggunakannya sebagai RDBMS.


46

Yah, dia salah dalam kasus umum.

Basis data dapat mengoptimalkan menggunakan berbagai metode, dibantu oleh petunjuk pengoptimal, indeks tabel, hubungan kunci asing dan mungkin informasi spesifik vendor database lainnya.


1
Saya harus mengakui ketika saya mulai bekerja dengan database saya memiliki keyakinan yang sama bahwa saya bisa mengalahkan kinerja gabungan. Tetapi tidak butuh waktu lama untuk menyadari betapa cepatnya penggabungan dilakukan oleh DB. Sebenarnya saya akan mengatakan dalam situasi ini lebih baik untuk membicarakannya dengan karyawan secara terbuka daripada mengabaikannya sebagai orang idiot.
LegendLength

1
@LegendLength Saya akan mengatakan itu bahkan benar jika mereka tidak begitu pintar. Tidak perlu mengasumsikan kecerdasan karena mereka melakukan kesalahan yang sama seperti yang kita ingat membuat (pada kenyataannya, bagi saya itu mungkin berarti mereka tidak begitu pintar ...) Ini lebih sederhana: Jarang membantu untuk bersikap meremehkan. Tidak apa-apa salah, sesekali!
lihat

24

Tidak, seharusnya tidak.

Database secara khusus dirancang untuk memanipulasi set data (jelas ....). Karena itu mereka sangat efisien dalam melakukan ini. Dengan melakukan apa yang pada dasarnya adalah penggabungan manual dalam kode sendiri, ia berusaha mengambil alih peran sesuatu yang dirancang khusus untuk pekerjaan itu. Kemungkinan kodenya pernah seefisien yang ada di basis data sangat jauh.

Sebagai tambahan, tanpa bergabung, apa gunanya menggunakan database? dia mungkin juga hanya menggunakan file teks.


2
Bahkan tanpa bergabung? Pemetaan in-memory otomatis, caching query otomatis, banyak hal automagic lainnya yang tidak terjadi sama sekali dengan kebanyakan sistem file. Oh, apakah saya menyebutkan transaksi yang dapat dikendalikan dengan baik?
Piskvor meninggalkan gedung

19

Jika "malas" didefinisikan sebagai orang yang ingin menulis lebih sedikit kode, maka saya setuju. Jika "malas" didefinisikan sebagai orang yang ingin memiliki alat melakukan apa yang mereka lakukan dengan baik, saya setuju. Jadi jika dia hanya setuju dengan Larry Wall (mengenai atribut programmer yang baik), maka saya setuju dengannya.


Saya menambahkan ketepatan malas: untuk orang malas yang tidak peduli dengan penampilan dan lebih suka menulis lebih sedikit kode. Saya pikir bergabung adalah untuk orang-orang yang malas tetapi dalam hal ini bergabung juga lebih baik daripada beberapa permintaan.
Bastien Vandamme

3
@Ran Dane: Bergabung untuk orang malas, ya. Fakta bahwa mereka kemungkinan akan berkinerja baik adalah ortogonal.
Piskvor meninggalkan gedung

16

Ummm, bergabung adalah bagaimana database relasional menghubungkan tabel satu sama lain. Saya tidak yakin apa maksudnya.

Bagaimana membuat beberapa panggilan ke database menjadi lebih efisien daripada satu panggilan? Plus mesin sql dioptimalkan untuk melakukan hal semacam ini.

Mungkin rekan kerja Anda terlalu malas untuk belajar SQL.


12

Ya kamu harus.

Dan Anda harus menggunakan C ++ daripada C # karena kinerja. C # untuk orang malas.

Tidak tidak Tidak. Anda harus menggunakan C daripada C ++ karena kinerja. C ++ untuk orang malas.

Tidak tidak Tidak. Anda harus menggunakan perakitan alih-alih C karena kinerja. C untuk orang malas.

Ya, saya bercanda. Anda dapat membuat program lebih cepat tanpa bergabung dan Anda dapat membuat program menggunakan lebih sedikit memori tanpa bergabung. TAPI dalam banyak kasus, waktu pengembangan Anda lebih penting daripada waktu dan memori CPU. Berikan sedikit kinerja dan nikmati hidup Anda. Jangan buang waktu Anda untuk sedikit kinerja. Dan katakan padanya, "Mengapa kamu tidak membuat jalan raya langsung dari tempatmu ke kantormu?"


1
Saya telah melihat semua jawaban Anda sejauh ini dan itu sangat lucu. Tolong terus mereka datang. Entah itu atau, di mana saya dapat berlangganan blog Anda?
Gerry

11

"Ini benar secara teknis" - demikian pula, basis data SQL tidak berguna: apa gunanya menggunakan satu ketika Anda bisa mendapatkan hasil yang sama dengan menggunakan banyak file CSV, dan menghubungkannya dalam kode? Heck, abstraksi apa pun untuk orang malas, mari kita kembali ke pemrograman kode mesin tepat di perangkat keras! ;)

Juga, pernyataannya tidak benar dalam semua kasus kecuali kasus yang paling berbelit-belit: RDBMS sangat dioptimalkan untuk membuat GABUNGAN cepat . Relasional sistem manajemen database, kan?


2
1 Ungkapan "... teknis benar" akan bekerja lebih baik jika OP telah digunakan untuk kata unnecessaryyang agak uselessdalam kalimat sebelumnya. Mengatakan bahwa bergabung tidak berguna sama sekali tidak benar tanpa teknis yang perlu dipertimbangkan. Bagaimanapun, kesalahpahaman OP dan kolega tentang titik RDBMS tidak biasa: stackoverflow.com/q/5575682/47550
Paul Sasik

7

Perusahaan terakhir tempat saya bekerja juga tidak menggunakan SQL. Sebagai gantinya mereka memindahkan pekerjaan ini ke lapisan aplikasi yang dirancang untuk menskala secara horizontal. Alasan untuk desain ini adalah untuk menghindari pekerjaan di lapisan basis data. Biasanya database yang menjadi hambatan. Lebih mudah untuk mereplikasi layer aplikasi daripada database. Mungkin ada alasan lain. Tapi ini yang bisa saya ingat sekarang.

Ya, saya setuju bahwa gabungan yang dilakukan pada lapisan aplikasi tidak efisien dibandingkan dengan gabungan yang dilakukan oleh basis data. Lebih banyak komunikasi jaringan juga.

Harap dicatat bahwa saya tidak mengambil sikap keras untuk menghindari bergabungnya SQL.


Nah, itu terdengar seperti argumen rasional terhadap GABUNG dalam kasus spesifik Anda. Saya ingat bahwa FB Engineering memposting sesuatu yang serupa di blog mereka - meningkatkan skala juga merupakan prioritas utama mereka. Sayangnya, hanya sebagian kecil programmer yang perlu melakukan ini, tetapi banyak yang berpikir mereka melakukannya "karena OMG Facebook juga melakukan itu";)
Piskvor meninggalkan gedung

oke, dalam solusi perusahaan di mana Anda memiliki lalu lintas yang cukup untuk membebani server database ini mungkin layak dipertimbangkan tetapi lebih mungkin bahwa pelaporan prosedur tersimpan atau cadangan terjadwal memakukan kinerja. Basis data bagus untuk digabung, terutama jika ada ketidakmampuan untuk membantu
Jodrell

@Jodrell: Ya mereka pandai bergabung; sekali lagi, ada kasus sudut di mana Anda perlu menjatuhkan keanggunan bergabung untuk mendapatkan lebih banyak kekuatan. Saya telah bertemu satu situasi seperti itu; kami mencoba setiap solusi yang mungkin, dan memang solusi no-join adalah yang tercepat dalam satu situasi yang sangat spesifik . Dan tidak, sama sekali tidak ada yang berjalan di server tertentu; prosedur tersimpan tidak dapat memperlambat Anda jika Anda tidak punya;)
Piskvor meninggalkan gedung

5

Tanpa bergabung, bagaimana Anda akan menghubungkan item pesanan dengan pesanan? Itulah keseluruhan poin dari sistem manajemen basis data relasional. Tanpa bergabung, tidak ada data relasional dan Anda mungkin juga menggunakan file teks untuk memproses data.

Kedengarannya dia tidak mengerti konsepnya jadi dia berusaha membuatnya tampak tidak berguna. Dia tipe orang yang sama yang menganggap excel adalah aplikasi basis data. Tampar dia dengan konyol dan katakan padanya untuk membaca lebih lanjut tentang basis data. Membuat banyak koneksi dan menarik data dan menggabungkan data melalui C # adalah cara yang salah untuk melakukan sesuatu.


5

Saya tidak mengerti logika pernyataan "bergabung dalam SQL tidak berguna". Apakah berguna untuk memfilter dan membatasi data sebelum mengerjakannya? Ketika Anda responden lain telah menyatakan ini adalah apa yang dilakukan oleh mesin database, itu harus menjadi apa yang mereka kuasai.

Mungkin seorang programmer malas akan tetap berpegang pada teknologi yang mereka kenal dan menghindari kemungkinan lain karena alasan non teknis.

Saya menyerahkan kepada Anda untuk memutuskan.


5

Mari kita perhatikan contoh: tabel dengan catatan faktur, dan tabel terkait dengan catatan item baris faktur. Pertimbangkan kode semu klien:

for each (invoice in invoices)
    let invoiceLines = FindLinesFor(invoice)
...

Jika Anda memiliki 100.000 faktur dengan masing-masing 10 baris, kode ini akan mencari 10 baris faktur dari tabel 1 juta, dan itu akan melakukannya 100.000 kali. Saat ukuran tabel bertambah, jumlah operasi terpilih meningkat, dan biaya setiap operasi pilih meningkat.

Karena komputer cepat, Anda mungkin tidak melihat perbedaan kinerja antara kedua pendekatan jika Anda memiliki beberapa ribu catatan atau lebih sedikit. Karena kenaikan biaya lebih dari linier, karena jumlah catatan meningkat (dalam jutaan, katakanlah), Anda akan mulai melihat perbedaan, dan perbedaannya akan menjadi kurang dapat ditoleransi ketika ukuran kumpulan data bertambah.

Bergabung, bagaimanapun. akan menggunakan indeks tabel dan menggabungkan dua set data. Ini berarti Anda memindai tabel kedua secara efektif sekali daripada mengaksesnya secara acak sebanyak N kali. Jika ada kunci asing yang ditentukan, database sudah memiliki tautan antara catatan terkait yang disimpan secara internal.

Bayangkan melakukan ini sendiri. Anda memiliki daftar siswa dan buku catatan menurut abjad dengan semua laporan nilai siswa (satu halaman per kelas). Buku catatan diurutkan sesuai dengan nama siswa, dalam urutan yang sama dengan daftar. Bagaimana Anda memilih untuk melanjutkan?

  1. Baca nama dari daftar.
  2. Buka buku catatan.
  3. Temukan nama siswa.
  4. Baca nilai siswa, balik halaman sampai Anda mencapai siswa berikutnya atau halaman terakhir.
  5. Tutup buku catatan.
  6. Ulang.

Atau:

  1. Buka buku catatan ke halaman pertama.
  2. Baca nama dari daftar.
  3. Baca nilai apa pun untuk nama itu dari buku catatan.
  4. Ulangi langkah 2-3 sampai Anda mencapai akhir
  5. Tutup buku catatan.

5

Kedengarannya seperti kasus klasik " Saya bisa menulisnya lebih baik ." Dengan kata lain, dia melihat sesuatu yang dia lihat sebagai semacam rasa sakit di leher (menulis banyak gabungan dalam SQL) dan berkata, "Saya yakin saya bisa menulis yang lebih baik dan mendapatkan kinerja yang lebih baik." Anda harus bertanya kepadanya apakah dia a) lebih pintar dan b) lebih berpendidikan daripada orang biasa yang jauh di dalam kode optimasi Oracle atau SQL Server. Kemungkinannya bukan dia.


3

Dia tentu saja salah. Meskipun ada pro pasti untuk manipulasi data dalam bahasa seperti C # atau Java, bergabung paling cepat dalam database karena sifat SQL itu sendiri.

SQL terus merinci statistik mengenai data, dan jika Anda telah membuat indeks dengan benar, dapat dengan cepat menemukan satu catatan dalam beberapa juta. Selain fakta bahwa mengapa Anda ingin menyeret semua data Anda ke C # untuk bergabung ketika Anda bisa melakukannya langsung di tingkat basis data?

Pro untuk menggunakan C # ikut bermain ketika Anda perlu melakukan sesuatu secara iteratif. Jika Anda perlu melakukan beberapa fungsi untuk setiap baris, kemungkinan lebih cepat melakukannya dalam C #, jika tidak, menggabungkan data dioptimalkan dalam DB.


3

Saya akan mengatakan bahwa saya telah menemukan kasus di mana ia lebih cepat memecah kueri dan melakukan gabungan dalam kode. Yang sedang berkata, hanya dengan satu versi tertentu MySQL yang harus saya lakukan. Yang lainnya, basis data mungkin akan lebih cepat (perhatikan bahwa Anda mungkin harus mengoptimalkan kueri, tetapi itu akan tetap lebih cepat).


3

Saya menduga dia memiliki pandangan terbatas tentang apa yang harus digunakan untuk database. Salah satu pendekatan untuk memaksimalkan kinerja adalah membaca seluruh basis data ke dalam memori. Dalam situasi ini, Anda mungkin mendapatkan kinerja yang lebih baik dan Anda mungkin ingin melakukan gabungan jika memori untuk efisiensi. Namun ini tidak benar-benar menggunakan database, sebagai database IMHO.


3
Sebagian besar mesin basis data akan melakukan ini untuk Anda di belakang layar; dan misalnya di MySQL Anda dapat membuat tabel ( MEMORYmesin) murni dalam memori . Menerapkan kembali fungsi basis data tanpa basis data biasanya merupakan tanda kasus NIH yang parah;)
Piskvor meninggalkan gedung

@ phoog: Tidak Diciptakan Di Sini - dengan kata lain, "Saya tidak memikirkan itu, jadi tidak ada". Banyak roda persegi diciptakan kembali karena ini. (dan ya, kadang-kadang menciptakan kembali roda itu berguna, misalnya jika Anda membuat mobil balap; menciptakan kembali "hanya karena" tidak mungkin membuat Anda mendapatkan roda yang lebih baik)
Piskvor meninggalkan gedung

Dengan kata lain, "Saya tidak membuatnya jadi pasti sampah". Ini memiliki kebenaran hanya sejauh "Saya belum mengujinya sehingga mungkin tidak cocok untuk tujuan saya", jadi uji sebelum Anda menghakiminya.
Peter Lawrey

@Piskvor: Tidak harus, database hanya dapat menggunakan memori dari sistem yang dijalankannya, sedangkan aplikasi dapat menggunakan memori server aplikasi. Dengan kata lain: Jika basis data berada pada host khusus, mengakses cache masih memerlukan bandwidth jaringan dan tunduk pada latensi jaringan, tetapi cache apa pun yang disimpan aplikasi dapat ditanyakan dengan kecepatan latensi rendah dari akses memori.
meriton

2

Tidak, tidak hanya digabung dengan lebih baik dalam kode basis data yang ad-hoc C # / Java; tetapi biasanya beberapa teknik penyaringan dapat diterapkan, yang menghasilkan kinerja yang lebih baik.


2

Dia salah, bergabung adalah apa yang digunakan programmer yang kompeten. Mungkin ada beberapa kasus terbatas di mana metode yang diusulkannya lebih efisien (dan jika saya mungkin akan menggunakan database Documant) tetapi saya tidak bisa melihatnya jika Anda memiliki jumlah data yang layak. Misalnya, ambil kueri ini:

select t1.field1 
from table1 t1
join table2 t2 
    on t1.id = t2.id
where t1.field2 = 'test'

Asumsikan Anda memiliki 10 juta catatan di table1 dan 1 juta catatan di table2. Asumsikan 9 juta catatan dalam tabel 1 memenuhi klausa di mana. Asumsikan hanya 15 dari mereka ada di table2 juga. Anda dapat menjalankan pernyataan sql ini yang jika diindeks dengan benar akan mengambil milidetik dan mengembalikan 15 catatan di jaringan dengan hanya 1 kolom data. Atau Anda dapat mengirim sepuluh juta catatan dengan 2 kolom data dan secara terpisah mengirim 1 juta catatan lain dengan satu kolom data di seluruh jaringan dan menggabungkannya di server web.

Atau tentu saja Anda dapat menyimpan seluruh isi basis data di server web setiap saat yang benar-benar konyol jika Anda memiliki lebih dari jumlah data yang sepele dan data yang terus berubah. Jika Anda tidak membutuhkan kualitas database relasional maka jangan gunakan itu. Tetapi jika Anda melakukannya, maka gunakan dengan benar.


2

Saya sering mendengar argumen ini selama karier saya sebagai pengembang perangkat lunak. Hampir setiap kali dinyatakan, orang yang membuat klaim tidak memiliki banyak pengetahuan tentang sistem basis data relasional, cara kerjanya dan cara sistem tersebut harus digunakan.

Ya, bila digunakan secara tidak benar , bergabung tampaknya tidak berguna atau bahkan berbahaya. Tetapi ketika digunakan dengan cara yang benar, ada banyak potensi implementasi database untuk melakukan optimasi dan untuk "membantu" pengembang mengambil hasil yang benar dengan paling efisien.

Jangan lupa bahwa dengan menggunakan JOINAnda memberi tahu database tentang cara Anda mengharapkan potongan data saling berhubungan dan oleh karena itu memberikan database lebih banyak informasi tentang apa yang Anda coba lakukan dan karenanya membuatnya lebih sesuai dengan kebutuhan Anda.

Jadi jawabannya pasti: Tidak, JOINSsama sekali tidak berguna!


0

Ini "secara teknis benar" hanya dalam satu kasus yang tidak sering digunakan dalam aplikasi (ketika semua baris semua tabel dalam gabungan tersebut dikembalikan oleh kueri). Di sebagian besar kueri, hanya sebagian kecil dari baris setiap tabel yang dikembalikan. Mesin database sering menggunakan indeks untuk menghilangkan baris yang tidak diinginkan, kadang-kadang bahkan tanpa membaca baris yang sebenarnya karena dapat menggunakan nilai yang disimpan dalam indeks. Mesin basis data itu sendiri ditulis dalam C, C ++, dll. Dan setidaknya seefisien kode yang ditulis oleh pengembang.


0

Kecuali saya benar-benar salah paham, logika dalam pertanyaan itu sangat cacat

Jika ada 20 baris dalam B untuk setiap A, 1000 baris dalam A menyiratkan 20k baris dalam B. Tidak mungkin hanya 100 baris dalam B kecuali ada banyak-banyak tabel "AB" dengan 20k baris dengan berisi pemetaan .

Jadi untuk mendapatkan semua informasi tentang 20 dari 100 baris B peta untuk setiap baris A Anda meja AB juga. Jadi ini bisa berupa:

  • 3 set hasil dari 100, 1000, dan 20k baris dan satu klien BERGABUNG
  • satu hasil A-AB-B BERGABUNG ditetapkan dengan baris 20k

Jadi "GABUNG" di klien tidak menambah nilai apa pun saat Anda memeriksa data. Bukannya itu bukan ide yang buruk. Jika saya mengambil satu objek dari database daripada mungkin lebih masuk akal untuk memecahnya menjadi set hasil yang terpisah. Untuk panggilan jenis laporan, saya akan meratakannya menjadi hampir selalu.

Bagaimanapun, saya akan mengatakan hampir tidak ada gunanya untuk bergabung silang sebesar ini. Ini contoh yang buruk.

Anda harus BERGABUNG di suatu tempat, dan itulah keahlian RDBMS. Saya tidak ingin bekerja dengan monyet kode klien yang berpikir mereka bisa melakukan yang lebih baik.

Renungan:

Untuk bergabung dalam klien membutuhkan objek persisten seperti DataTables (dalam .net). Jika Anda memiliki satu hasil yang diratakan, ia dapat dikonsumsi melalui sesuatu yang lebih ringan seperti DataReader. Volume tinggi = banyak sumber daya klien yang digunakan untuk menghindari database. GABUNG.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.