Apakah BERGABUNG dengan kueri lebih cepat dari beberapa kueri? (Anda menjalankan permintaan utama Anda, dan kemudian Anda menjalankan banyak SELECT lain berdasarkan hasil dari permintaan utama Anda)
Saya bertanya karena BERGABUNG dengan mereka akan menyulitkan BANYAK desain aplikasi saya
Jika mereka lebih cepat, adakah yang bisa memperkirakan kurang lebih berapa banyak? Jika 1,5x saya tidak peduli, tetapi jika 10x saya kira saya lakukan.
mysql
database
join
query-optimization
Thomas Bonini
sumber
sumber
Jawaban:
Ini terlalu samar untuk memberi Anda jawaban yang relevan dengan kasus spesifik Anda. Itu tergantung pada banyak hal. Jeff Atwood (pendiri situs ini) sebenarnya menulis tentang ini . Namun, untuk sebagian besar, jika Anda memiliki indeks yang tepat dan Anda melakukan GABUNGAN dengan benar, biasanya akan lebih cepat untuk melakukan 1 perjalanan daripada beberapa.
sumber
Untuk gabungan dalam, satu permintaan masuk akal, karena Anda hanya mendapatkan baris yang cocok. Untuk gabungan kiri, banyak kueri jauh lebih baik ... lihat patokan yang saya lakukan berikut:
Permintaan tunggal dengan 5 Bergabung
permintaan: 8.074508 detik
ukuran hasil: 2268000
5 kueri berturut-turut
waktu permintaan gabungan: 0,00262 detik
ukuran hasil: 165 (6 + 50 + 7 + 12 + 90)
.
Perhatikan bahwa kami mendapatkan hasil yang sama dalam kedua kasus (6 x 50 x 7 x 12 x 90 = 2268000)
gabungan kiri menggunakan lebih banyak memori secara eksponensial dengan data yang berlebihan.
Batas memori mungkin tidak seburuk jika Anda hanya menggabungkan dua tabel, tetapi umumnya tiga atau lebih dan itu menjadi pertanyaan yang berbeda nilainya.
Sebagai catatan, server MySQL saya berada tepat di samping server aplikasi saya ... jadi waktu koneksi dapat diabaikan. Jika waktu koneksi Anda dalam hitungan detik, maka mungkin ada manfaatnya
jujur
sumber
Pertanyaan ini sudah lama, tetapi tidak memiliki beberapa tolok ukur. Saya membandingkan BERGABUNG dengan 2 pesaingnya:
WHERE IN(...)
atau setaraHasilnya adalah jelas: pada MySQL,
JOIN
adalah jauh lebih cepat. N + 1 kueri dapat menurunkan kinerja aplikasi secara drastis:Yaitu, kecuali jika Anda memilih banyak catatan yang menunjukkan sejumlah kecil catatan asing yang berbeda. Berikut ini adalah patokan untuk kasus ekstrim:
Ini sangat tidak mungkin terjadi dalam aplikasi tipikal, kecuali jika Anda bergabung dengan hubungan-ke-banyak, dalam hal ini kunci asing ada di tabel lain, dan Anda menduplikasi data tabel utama berkali-kali.
Bawa pulang:
JOIN
Lihat artikel saya di Media untuk informasi lebih lanjut.
sumber
Saya benar-benar datang ke pertanyaan ini mencari jawaban sendiri, dan setelah membaca jawaban yang diberikan saya hanya bisa setuju bahwa cara terbaik untuk membandingkan kinerja permintaan DB adalah untuk mendapatkan angka dunia nyata karena hanya ada banyak variabel yang harus diperhitungkan TETAPI, saya juga berpikir bahwa membandingkan angka-angka di antara keduanya tidak ada gunanya di hampir semua kasus. Yang saya maksud adalah bahwa angka-angka harus selalu dibandingkan dengan angka yang dapat diterima dan jelas tidak dibandingkan satu sama lain.
Saya bisa mengerti jika satu cara query membutuhkan waktu 0,02 detik dan yang lain membutuhkan waktu 20 detik, itu perbedaan yang sangat besar. Tetapi bagaimana jika satu cara query membutuhkan 0,0000000002 detik, dan yang lainnya membutuhkan 0,0000002 detik? Dalam kedua kasus satu cara adalah kekalahan 1000 kali lebih cepat daripada yang lain, tetapi apakah itu benar - benar masih "kekalahan" dalam kasus kedua?
Intinya seperti yang saya pribadi melihatnya: jika berkinerja baik, pilih solusi yang mudah.
sumber
Lakukan tes cepat memilih satu baris dari tabel 50.000 baris dan bergabung dengan satu baris dari tabel 100.000 baris. Pada dasarnya tampak seperti:
vs.
Metode dua pilihan mengambil 3,7 detik untuk 50.000 membaca sedangkan JOIN mengambil 2,0 detik pada komputer lambat di rumah saya. INNER JOIN dan LEFT JOIN tidak membuat perbedaan. Mengambil beberapa baris (misalnya, menggunakan IN SET) menghasilkan hasil yang serupa.
sumber
Pertanyaan sebenarnya adalah: Apakah catatan-catatan ini memiliki hubungan satu-ke-satu atau hubungan satu-ke-banyak ?
Jawaban TLDR:
Jika satu-ke-satu, gunakan
JOIN
pernyataan.Jika satu-ke-banyak, gunakan satu (atau banyak)
SELECT
pernyataan dengan optimasi kode sisi-server.Mengapa dan Cara Menggunakan SELECT untuk Optimasi
SELECT
(dengan beberapa kueri alih-alih bergabung) pada kelompok besar catatan berdasarkan hubungan satu-ke-banyak menghasilkan efisiensi yang optimal, karenaJOIN
memiliki masalah kebocoran memori yang eksponensial. Raih semua data, lalu gunakan bahasa skrip sisi server untuk mengurutkannya:Hasil:
Di sini, saya mendapatkan semua catatan, dalam satu pernyataan pilih. Ini lebih baik daripada
JOIN
, yang akan mendapatkan sekelompok kecil catatan ini, satu per satu, sebagai sub-komponen dari permintaan lain. Lalu saya menguraikannya dengan kode sisi server yang terlihat seperti ...Kapan Tidak Menggunakan GABUNG untuk Optimasi
JOIN
'ing sekelompok besar catatan berdasarkan pada hubungan satu-ke-satu dengan satu catatan tunggal menghasilkan efisiensi yang optimal dibandingkan dengan beberapaSELECT
pernyataan, satu demi satu, yang hanya mendapatkan jenis catatan berikutnya.Tetapi
JOIN
tidak efisien ketika mendapatkan catatan dengan hubungan satu-ke-banyak.Contoh: Basis data Blog memiliki 3 tabel minat, Blogpost, Tag, dan Komentar.
Jika ada 1 blogpost, 2 tag, dan 2 komentar, Anda akan mendapatkan hasil seperti:
Perhatikan bagaimana setiap rekaman digandakan. Oke, jadi, 2 komentar dan 2 tag adalah 4 baris. Bagaimana jika kita memiliki 4 komentar dan 4 tag? Anda tidak mendapatkan 8 baris - Anda mendapatkan 16 baris:
Tambahkan lebih banyak tabel, lebih banyak catatan, dll., Dan masalah akan dengan cepat mengembang ke ratusan baris yang semuanya penuh dengan sebagian besar data yang berlebihan.
Berapa biaya duplikat ini bagi Anda? Memori (di server SQL dan kode yang mencoba untuk menghapus duplikat) dan sumber daya jaringan (antara SQL server dan server kode Anda).
Sumber: https://dev.mysql.com/doc/refman/8.0/en/nested-join-optimization.html ; https://dev.mysql.com/doc/workbench/en/wb-relationship-tools.html
sumber
Buat kueri dan gabungkan yang terpisah, lalu tentukan waktu masing-masing - tidak ada yang lebih membantu daripada angka dunia nyata.
Kemudian bahkan lebih baik - tambahkan "JELASKAN" ke awal setiap permintaan. Ini akan memberi tahu Anda berapa banyak subqueries yang digunakan MySQL untuk menjawab permintaan Anda akan data, dan berapa banyak baris yang dipindai untuk setiap permintaan.
sumber
Bergantung pada kompleksitas untuk database dibandingkan dengan kompleksitas pengembang, mungkin lebih mudah untuk melakukan banyak panggilan SELECT.
Coba jalankan beberapa statistik basis data terhadap JOIN dan beberapa SELECTS. Lihat apakah di lingkungan Anda GABUNG lebih cepat / lebih lambat dari SELECT.
Kemudian lagi, jika mengubahnya menjadi BERGABUNG akan berarti hari tambahan / minggu / bulan pekerjaan dev, saya akan tetap dengan beberapa SELECT
Bersulang,
BLT
sumber
Dalam pengalaman saya, saya telah menemukan itu biasanya lebih cepat untuk menjalankan beberapa permintaan, terutama ketika mengambil set data yang besar.
Ketika berinteraksi dengan database dari aplikasi lain, seperti PHP, ada argumen satu perjalanan ke server lebih banyak.
Ada cara lain untuk membatasi jumlah perjalanan yang dilakukan ke server dan masih menjalankan beberapa kueri yang seringkali tidak hanya lebih cepat tetapi juga membuat aplikasi lebih mudah dibaca - misalnya mysqli_multi_query.
Saya bukan pemula dalam hal SQL, saya pikir ada kecenderungan untuk pengembang, terutama junior untuk menghabiskan banyak waktu mencoba untuk menulis gabungan yang sangat pintar karena mereka terlihat pintar, sedangkan sebenarnya ada cara pintar untuk mengekstrak data yang terlihat sederhana.
Paragraf terakhir adalah pendapat pribadi, tetapi saya harap ini membantu. Saya setuju dengan yang lain meskipun yang mengatakan Anda harus melakukan benchmark. Tidak ada pendekatan yang merupakan peluru perak.
sumber
Apakah Anda harus menggunakan gabung adalah yang pertama dan terpenting tentang apakah gabung masuk akal . Hanya pada titik itu kinerja bahkan sesuatu untuk dipertimbangkan, karena hampir semua kasus lain akan menghasilkan kinerja yang jauh lebih buruk .
Perbedaan kinerja sebagian besar akan dikaitkan dengan seberapa terkait info yang Anda tanyakan. Bergabung bekerja, dan mereka cepat ketika data terkait dan Anda mengindeks barang dengan benar, tetapi mereka sering menghasilkan redundansi dan terkadang lebih banyak hasil daripada yang dibutuhkan. Dan jika set data Anda tidak terkait langsung, menempelkannya dalam satu permintaan tunggal akan menghasilkan apa yang disebut produk Cartesian (pada dasarnya, semua kemungkinan kombinasi baris), yang hampir tidak pernah seperti yang Anda inginkan.
Ini sering disebabkan oleh hubungan banyak ke satu. Misalnya, jawaban HoldOffHunger menyebutkan satu permintaan untuk posting, tag, dan komentar. Komentar terkait dengan posting, seperti halnya tag ... tetapi tag tidak terkait dengan komentar.
Dalam hal ini, jelas lebih baik untuk ini menjadi setidaknya dua pertanyaan terpisah. Jika Anda mencoba bergabung dengan tag dan komentar, karena tidak ada hubungan langsung antara keduanya, Anda berakhir dengan setiap kemungkinan kombinasi tag dan komentar.
many * many == manymany
. Selain itu, karena pos dan tag tidak terkait, Anda dapat melakukan dua kueri secara paralel, yang mengarah ke potensi keuntungan.Mari kita pertimbangkan skenario yang berbeda: Anda ingin komentar dilampirkan ke posting, dan info kontak komentator.
Di sinilah Anda harus mempertimbangkan bergabung. Selain sebagai permintaan yang jauh lebih alami, kebanyakan sistem basis data (termasuk MySQL) memiliki banyak orang pintar yang menaruh banyak kerja keras dalam mengoptimalkan permintaan seperti itu. Untuk kueri yang terpisah, karena setiap kueri bergantung pada hasil yang sebelumnya, kueri tidak dapat dilakukan secara paralel, dan total waktu menjadi tidak hanya waktu eksekusi aktual kueri, tetapi juga waktu yang dihabiskan untuk mengambil hasil, memilah melalui mereka untuk ID untuk kueri berikutnya, menghubungkan baris bersama, dll.
sumber
Apakah akan lebih cepat dalam hal throughput? Mungkin. Tetapi juga berpotensi mengunci lebih banyak objek basis data sekaligus (tergantung pada basis data dan skema Anda) dan dengan demikian mengurangi konkurensi. Dalam pengalaman saya, orang sering disesatkan oleh argumen "round-trip basis data yang lebih sedikit" ketika pada kenyataannya pada sebagian besar sistem OLTP di mana basis data berada pada LAN yang sama, hambatan sebenarnya jarang pada jaringan.
sumber
Berikut ini adalah tautan dengan 100 pertanyaan yang berguna, ini diuji dalam database Oracle tetapi ingat SQL adalah standar, apa yang berbeda antara Oracle, MS SQL Server, MySQL, dan database lain adalah dialek SQL:
http://javaforlearn.com/100-sql-queries-learn/
sumber
Ada beberapa faktor yang berarti tidak ada jawaban biner. Pertanyaan tentang apa yang terbaik untuk kinerja tergantung pada lingkungan Anda. Omong-omong, jika pilihan tunggal Anda dengan pengidentifikasi bukan sub-detik, ada sesuatu yang salah dengan konfigurasi Anda.
Pertanyaan sebenarnya untuk ditanyakan adalah bagaimana Anda ingin mengakses data. Pilihan tunggal mendukung pengikatan lambat. Misalnya jika Anda hanya menginginkan informasi karyawan, Anda dapat memilih dari tabel Karyawan. Hubungan kunci asing dapat digunakan untuk mengambil sumber daya terkait di lain waktu dan sesuai kebutuhan. Para pemilih akan sudah memiliki kunci untuk ditunjukkan sehingga mereka harus sangat cepat, dan Anda hanya perlu mengambil apa yang Anda butuhkan. Latensi jaringan harus selalu diperhitungkan.
Bergabung akan mengambil semua data sekaligus. Jika Anda membuat laporan atau mengisi kisi, ini mungkin yang Anda inginkan. Gabungan yang dikompilasi dan dioptimalkan hanya akan lebih cepat daripada pilihan tunggal dalam skenario ini. Ingat, bergabung Ad-hoc mungkin tidak secepat - Anda harus mengkompilasi mereka (ke dalam proc yang disimpan). Jawaban kecepatan tergantung pada rencana eksekusi, yang merinci langkah apa yang diambil DBMS untuk mengambil data.
sumber
Ya, satu permintaan menggunakan GABUNG akan lebih cepat. Meskipun tanpa mengetahui hubungan tabel yang Anda tanyakan, ukuran dataset Anda, atau di mana kunci utama berada, hampir tidak mungkin untuk mengatakan seberapa jauh lebih cepat.
Mengapa tidak menguji kedua skenario, maka Anda akan tahu pasti ...
sumber