Gunakan MySQL untuk secara teratur melakukan multi-way joins di 100+ GB tables?


11

Latar Belakang :
Saya telah membuat aplikasi web yang ingin saya ukur dengan cukup baik. Saya tahu saya bukan Google atau Twitter, tetapi aplikasi saya menggunakan jumlah data yang cukup besar untuk setiap pengguna dan karenanya memiliki persyaratan data yang cukup tinggi. Saya ingin siap untuk mengukur dengan cukup baik tanpa harus merancang ulang semuanya nanti.

Saya menganggap diri saya seorang pengembang perangkat lunak, bukan ahli basis data. Itu sebabnya saya memposting di sini. Semoga seseorang dengan keahlian database yang lebih banyak dapat memberi saya saran.

Dengan jumlah pengguna yang relatif besar, tetapi tidak seperti angka Facebook, saya berharap memiliki DB yang terlihat seperti ini:

Satu "Big table":

  • 250 juta catatan
  • 20 kolom
  • Sekitar 100 GB data
  • Memiliki kunci asing bigint (20) yang diindeks
  • Memiliki kolom string_id varchar (500) yang diindeks
  • Memiliki kolom "nilai" int (11)

4 tabel lainnya:

  • 10 juta catatan masing-masing
  • Masing-masing sekitar 2 - 4 GB data
  • masing-masing tabel ini memiliki 4 - 8 kolom
  • satu kolom adalah datetime date_created
  • satu kolom adalah kolom string_id varchar (500)
  • satu atau dua kolom dari masing-masing tabel ini akan dipilih dalam gabungan

Salah satu tabel ini digunakan untuk menyimpan rata-rata - skemanya adalah bigint (20) id, varchar (20) string_id, datetime date_created, float average_value

Apa yang ingin saya lakukan - dua pertanyaan yang relatif mahal:

  1. Hitung nilai rata-rata baru:

    • Menggunakan kunci asing, pilih hingga beberapa juta catatan terpisah dari tabel besar.
    • Hitung rata-rata baru, kelompokkan dengan string_id.
    • Masukkan hasil ke dalam tabel rata-rata.
    • Seperti yang saat ini dibangun, permintaan ini menggunakan dua gabungan.
  2. Buat catatan yang tidak dinormalisasi dan hanya-baca untuk melayani pengguna:

    • Gunakan kunci asing untuk memilih di mana saja dari 1.000-40.000 catatan dari tabel besar.
    • Bergabung dengan masing-masing dari empat tabel lainnya pada catatan terbaru dengan kolom id string.
    • Masukkan hasilnya ke dalam tabel yang tidak dinormalisasi.
    • Catatan-catatan ini untuk digunakan oleh front-end untuk menampilkan informasi kepada pengguna.
    • Saat ini dibangun, permintaan ini menggunakan empat bergabung.

Saya berencana untuk menjalankan masing-masing pertanyaan mahal ini pada database back-end batch yang akan mendorong hasilnya ke server DB front-end real-time yang menangani permintaan dari pengguna. Kueri ini akan dijalankan secara berkala. Saya belum memutuskan seberapa sering. Permintaan rata-rata dapat dilakukan mungkin sekali sehari. Permintaan de-normalisasi harus lebih sering - mungkin setiap beberapa menit.

Setiap pertanyaan ini saat ini berjalan dalam beberapa detik di MySQL pada mesin yang sangat low-end dengan dataset dengan catatan 100 ribu dalam "tabel besar." Saya prihatin dengan kemampuan saya untuk mengukur dan biaya penskalaan.

Pertanyaan :

  1. Apakah pendekatan ini terdengar masuk akal? Apakah ada yang salah dengan perspektif besar?
  2. Apakah RDBMS alat yang tepat, atau haruskah saya melihat solusi "data besar" lainnya seperti sesuatu dalam keluarga Hadoop? Kecenderungan saya adalah menggunakan RDBMS karena data terstruktur dan cocok dengan model relasional. Namun pada titik tertentu, menurut pemahaman saya bahwa saya mungkin tidak lagi dapat menggunakan RDBMS. Benarkah itu? Kapan saklar ini dibutuhkan?
  3. Apakah ini akan berhasil? Bisakah pertanyaan ini dijalankan dalam jumlah waktu yang wajar? Saya bisa menunggu beberapa jam untuk kueri # 1, tetapi kueri # 2 akan selesai dalam hitungan menit.
  4. Apa yang harus saya pertimbangkan dari perspektif perangkat keras? Seperti apa kemungkinan bottleneck RAM dan CPU saya? Saya menganggap menjaga indeks dalam RAM adalah penting. Apakah ada hal lain yang harus saya pertimbangkan?
  5. Pada titik tertentu saya mungkin harus mempartisi data saya dan menggunakan beberapa server. Apakah use case saya sepertinya sudah dalam kategori itu, atau akankah saya dapat mengukur satu mesin secara vertikal untuk sementara waktu? Apakah ini akan berfungsi dengan 10x data? 100x?

Yang ini sulit untuk dijawab dengan teliti. Mungkin Anda lebih baik meneliti tentang karakteristik kinerja permintaan MySQL secara umum sehingga Anda tahu apa yang dapat Anda harapkan .; Satu hal yang selalu dapat Anda lakukan tentu saja adalah menempatkan 20 disk di server sehingga Anda dapat membaca pada 3GB / s atau lebih. Tapi saya pikir Anda mencari jawaban hanya perangkat lunak yang menyeluruh.
usr

Jawaban:


4

Sudahkah Anda mencoba menumpuk lebih banyak data dan membandingkannya? Baris 100K tidak penting. Coba 250M atau 500M seperti yang Anda harapkan Anda harus menangani dan melihat di mana kemacetan.

RDBMS dapat melakukan banyak hal jika Anda memperhatikan dengan cermat keterbatasan dan mencoba dan bekerja dengan kekuatan sistem. Mereka sangat pandai dalam beberapa hal, dan mengerikan dalam hal-hal lain, jadi Anda perlu bereksperimen untuk memastikan itu pas.

Untuk beberapa pekerjaan pemrosesan batch, Anda benar-benar tidak dapat mengalahkan file datar, memuat data ke dalam RAM, menghancurkannya menggunakan serangkaian loop dan variabel sementara, dan membuang hasilnya. MySQL tidak akan pernah bisa menandingi kecepatan semacam itu, tetapi jika disetel dengan benar dan digunakan dengan benar, ia bisa mencapai urutan besarnya.

Apa yang ingin Anda lakukan adalah menyelidiki bagaimana data Anda dapat dipartisi. Apakah Anda memiliki satu set data besar dengan terlalu banyak jalur silang untuk dapat membaginya, atau adakah tempat alami untuk mempartisi itu? Jika Anda dapat mempartisi itu, Anda tidak akan memiliki satu tabel dengan setumpuk baris, tetapi berpotensi banyak yang secara signifikan lebih kecil. Tabel yang lebih kecil, dengan indeks yang jauh lebih kecil, cenderung berkinerja lebih baik.

Dari perspektif perangkat keras, Anda harus menguji untuk melihat kinerja platform Anda. Terkadang ingatan sangat penting. Lain kali itu disk I / O. Itu benar-benar tergantung pada apa yang Anda lakukan dengan data. Anda harus memperhatikan penggunaan CPU Anda dan mencari IO tingkat tinggi menunggu untuk mengetahui di mana masalahnya.

Kapan pun memungkinkan, bagi data Anda menjadi beberapa sistem. Anda dapat menggunakan MySQL Cluster jika Anda merasa berani, atau hanya memutar banyak contoh independen dari MySQL di mana masing-masing menyimpan bagian sewenang-wenang dari kumpulan data lengkap menggunakan beberapa skema partisi yang masuk akal.


@ Tomman Terima kasih atas saran Anda. Saya menyadari tidak ada pengganti untuk benar-benar mencobanya. Saya belum membandingkannya dengan baris 250 juta karena saya pertama kali ingin memastikan bahwa tidak ada yang salah dengan pendekatan saya. Sepertinya tidak ada. Selain itu, mendapatkan data sebanyak itu, dan melakukannya dengan cara yang agak realistis adalah tantangan yang belum saya pecahkan. Saya punya beberapa cara potensial untuk mempartisi data. Saya kira saya selanjutnya hanya akan mencoba meningkatkan data saya dan melihat bagaimana hasilnya di berbagai pos pemeriksaan - 1M, 10M, 100M, dll.
xnickmx

1

Tabel Ringkasan.

Setiap hari, hitung informasi agregat untuk data hari itu. Taruh itu di tabel "ringkasan". Lakukan pertanyaan Anda terhadap mereka. Mudah 10 kali lebih cepat.

Untuk diskusi lebih lanjut, berikan

  • SHOW CREATE TABLE (seperti sekarang)
  • Ukuran meja (yang telah Anda sebutkan)
  • SELECT yang Diusulkan

Beberapa hal yang jelas ...

  • BIGINT jarang dibenarkan. Dibutuhkan 8 byte. INT UNSIGNED mengambil 4 dan memungkinkan nilai 0,4billion. Dan ada MEDIUMINT, dll.
  • Beberapa indeks pada tabel 'fakta' biasanya merupakan masalah kinerja yang serius, terutama untuk INSERT. Apakah Anda mengalami masalah di sana?
  • DATETIME adalah 8 byte; TIMESTAMP adalah 4
  • KENDALA KUNCI ASING eksplisit bagus, tapi mahal
  • GABUNG mungkin atau mungkin bukan masalah kinerja; perlu melihat SELECT dan BUAT.
  • 100GB adalah ukuran yang bagus untuk database MySQL 'besar'; Saya menduga itu dapat dibuat untuk bekerja tanpa Hadoop, dll. Saya berurusan dengan satu db sekarang - sebagian besar halaman UI merespons dalam waktu kurang dari satu detik meskipun datanya cukup terlibat.
  • Apakah Anda akan 'membersihkan' data di beberapa titik? (Ini mengarah ke kasus penggunaan utama untuk PARTITIONing.)

"Lebih kecil -> lebih banyak cacheable -> lebih cepat


0

Untuk menyajikan data ujung depan Anda, kecuali ada sekumpulan dan sekumpulan sisipan sepanjang waktu, Anda benar-benar tidak dapat mengalahkan menggunakan pemicu untuk menyisipkan ke dalam tampilan material yang disimpan dalam sinkronisasi dengan ujung belakang tetapi dioptimalkan untuk melayani data. Tentu saja, Anda harus tetap bergabung, dll, dll, ke minimum pemicu ini. Salah satu strategi yang saya gunakan adalah memasukkan antrian sisipan / pembaruan ini ke tabel perantara dan kemudian mengirimkannya setiap menit atau lebih. Jauh lebih mudah untuk mengirim satu catatan dari 4 GB catatan. 4 GB data membutuhkan waktu lama untuk streaming bahkan jika Anda dapat menemukan catatan yang Anda cari dengan cepat.

Saya setuju dengan tadman. Yang terbaik adalah profil itu dengan jenis data yang Anda harapkan pada jenis sistem yang Anda inginkan.


Seperti yang saya sebutkan di posting saya, pandangan bergantung pada kueri yang menggunakan empat bergabung di seluruh tabel dengan puluhan juta catatan, jadi saya tidak benar-benar melihat bagaimana tampilan terwujud akan membantu.
xnickmx

Pemicu mungkin tidak cukup cepat untuk database ukuran ini. Berapa banyak INSERT per detik yang terjadi?
Rick James

1
@xnickmx Jika tidak ada begitu banyak sisipan / pembaruan, pemicu membuatnya mudah / berkinerja untuk menjaga data yang didenormalkan dalam sinkronisasi. Jika perlu lebih cepat untuk memasukkan / memperbarui, antri mereka dengan sesuatu seperti ini: blog.shlomoid.com/2008/04/… atau membuat sendiri. Dengan cara ini Anda tidak harus bergabung dengan 100 juta tabel baris yang ada untuk mendapatkan data baru karena ketika pemicu kebakaran, Anda mengambil keuntungan dari fakta bahwa Anda mengetahui data baru saat itu dan hanya dapat mendenormalkannya sebagai bagian dari tx atau antri untuk denasionalisasi nanti.
wes.stueve

@ RickJames Setuju. Anda harus memperhitungkan jumlah sisipan untuk jenis strategi ini dan seberapa cepat mereka harus memproses.
wes.stueve
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.