Peluang perancangan ulang basis data: Desain tabel apa yang digunakan untuk pengumpulan data sensor ini?

13

Latar Belakang

Saya memiliki jaringan sekitar 2000 sensor, yang masing-masing memiliki sekitar 100 titik data yang kami kumpulkan dalam interval 10 menit. Titik data ini biasanya nilai int, tetapi beberapa adalah string dan float. Data ini harus disimpan selama 90 hari, lebih jika memungkinkan dan masih efisien.

Desain Basis Data

Ketika awalnya ditugaskan dengan proyek ini, saya menulis aplikasi C # yang menulis file yang dipisahkan koma untuk setiap sensor. Saat itu jumlahnya tidak banyak, ketika seseorang ingin melihat tren, kami akan membuka csv di Excel dan membuat grafik sesuai kebutuhan.

Banyak hal tumbuh dan kami beralih ke database MySQL. Saya membuat tabel untuk setiap sensor (ya saya tahu, banyak tabel!); telah bekerja dengan baik, tetapi memiliki beberapa keterbatasan. Dengan begitu banyak tabel, jelas tidak mungkin untuk menulis kueri yang akan menemukan data di antara semua sensor ketika mencari nilai tertentu.

Untuk versi berikutnya, saya beralih ke Microsoft SQL Server Express, dan memasukkan semua data sensor ke dalam satu tabel besar. Ini juga berfungsi, dan memungkinkan kami melakukan kueri untuk menemukan nilai di antara semua sensor yang menarik. Namun, saya berlari ke batas 10GB untuk versi Express, dan telah memutuskan untuk beralih kembali ke MySQL daripada berinvestasi di SQL Server Standard.

Pertanyaan

Saya senang dengan kinerja dan skalabilitas MySQL, tetapi saya tidak yakin apakah tetap menggunakan pendekatan all-data-in-one-table yang terbaik. 10GB dalam satu meja sepertinya meminta desain yang berbeda. Saya harus menyebutkan bahwa kebutuhan untuk meminta data untuk grafik masih ada, dan saya khawatir bahwa akan ada masalah kinerja untuk permintaan yang menggambarkan, misalnya, data suhu untuk satu sensor selama 90 hari penuh. (Dengan kata lain grafik harus menjadi sesuatu yang cepat untuk diproduksi, tanpa menunggu SQL untuk memilah-milah tumpukan data hanya untuk mengisolasi sensor yang menarik.)

Haruskah saya membagi tabel ini dalam beberapa cara untuk meningkatkan kinerja? Atau bukan tidak biasa memiliki meja sebesar itu?

Saya memiliki indeks pada ID Sensor dan kolom Timestamp, yang merupakan batas yang menentukan untuk setiap pertanyaan. (yaitu mendapatkan data untuk sensor X dari waktu A ke waktu B).

Saya sudah membaca sedikit tentang sharding dan partisi, tetapi tidak merasa itu sesuai untuk kasus ini.


Edit:

Berdasarkan komentar dan jawaban sejauh ini, beberapa info tambahan mungkin bermanfaat:

Bukan Penyimpanan Tidak Terbatas: Saat ini saya tidak menyimpan data selama 90 hari. Setiap hari, saya menjalankan kueri yang menghapus data yang lebih lama dari 90 hari. Jika itu menjadi penting di masa depan, saya akan menyimpan lebih banyak, tetapi untuk saat ini sudah cukup. Ini membantu menjaga ukuran dalam pemeriksaan dan kinerja tinggi (er).

Tipe Mesin: Implementasi MySQL asli menggunakan MyISAM. Saat membuat tabel saat ini untuk implementasi baru (satu tabel data bukan banyak) mereka sudah default ke InnoDB. Saya tidak percaya saya memiliki persyaratan untuk satu atau yang lain.

Normalisasi: Tentu saja ada tabel lain selain tabel pengumpulan data. Tabel dukungan ini menyimpan hal-hal seperti informasi jaringan untuk sensor, informasi masuk untuk pengguna, dll. Tidak banyak yang bisa dinormalisasi (sejauh yang saya tahu). Alasan tabel data memiliki begitu banyak kolom adalah karena ada banyak variabel dari masing-masing sensor. (Beberapa suhu, tingkat cahaya, tekanan udara, dll.) Normalisasi bagi saya berarti tidak ada data yang berlebihan atau kelompok yang berulang. (Setidaknya untuk 1NF.) Untuk sensor yang diberikan, menyimpan semua nilai pada waktu tertentu memerlukan satu baris data dan tidak ada hubungan 1: N yang terlibat di sana (yang saya lihat).

Saya dapat memecah tabel secara fungsional, membuat (misalnya) semua nilai yang berhubungan dengan suhu dalam satu tabel, dan semua nilai yang berhubungan dengan tekanan udara di meja lainnya. Meskipun ini dapat meningkatkan efisiensi bagi seseorang yang membuat kueri hanya-suhu, saya masih harus memasukkan semua data sekaligus. Namun, peningkatan efisiensi mungkin bermanfaat untuk operasi SELECT. Jelas saya akan lebih baik memecah tabel secara vertikal berdasarkan seberapa sering pengguna meminta data. Mungkin ini yang harus saya lakukan. Saya kira dalam mengajukan pertanyaan, saya mencari konfirmasi bahwa melakukan ini akan bermanfaat.


Edit 2:

Penggunaan Data: Pada akhirnya banyak data yang tidak pernah dilihat atau dibutuhkan, karena kami biasanya hanya berfokus pada item yang bermasalah. Tetapi dalam upaya menemukan masalah, kami menggunakan berbagai alat untuk mencari data dan menentukan item apa yang diperbesar.

Sebagai contoh, kami melihat korelasi antara nilai penggunaan memori (program perangkat lunak berpemilik khusus pelanggan) dan reboot / crash. Salah satu poin data yang saya kumpulkan terkait dengan penggunaan memori ini, dan saya dapat melihat data historis untuk menunjukkan bahwa perangkat menjadi tidak stabil setelah penggunaan memori tertentu terlampaui. Hari ini, untuk subset perangkat yang menjalankan perangkat lunak ini, saya memeriksa nilai ini dan mengeluarkan perintah reboot jika terlalu tinggi. Sampai ini ditemukan, saya tidak berpikir mengumpulkan data ini bernilai.

Untuk alasan ini, saya berpendapat bahwa sekitar 100 titik data dikumpulkan dan disimpan, bahkan jika nilainya dipertanyakan. Tetapi dalam penggunaan normal sehari-hari, pengguna biasanya memeriksa mungkin selusin parameter ini. Jika pengguna tertarik pada area geografis tertentu, ia dapat (menggunakan perangkat lunak) menghasilkan grafik atau spreadsheet data untuk mungkin beberapa lusin sensor. Tidak jarang melihat grafik 30 hari dengan dua atau tiga garis plot yang menunjukkan hal-hal seperti suhu, tekanan udara, dan tingkat cahaya. Melakukan ini akan menjalankan kueri yang mirip dengan ini:

SELECT sensor_id, location, data_timestamp, temp1, air1, light1
FROM data
WHERE data_timestamp >= '2012-02-01'
AND sensor_id IN (1, 2, 3);

(Dalam versi MySQL asli, di mana setiap sensor memiliki tabel sendiri, tiga pertanyaan terpisah akan dikeluarkan, tetapi hasilnya digabungkan dalam perangkat lunak untuk membuat grafik.)

Karena datatabel berisi begitu banyak baris (~ 10 juta), meskipun memiliki indeks iddan data_timestamp, kinerja terutama lebih buruk daripada skenario multi-tabel (4.500 baris dikembalikan dalam 9 detik dibandingkan dengan kurang dari satu detik dengan contoh ini). Kemampuan untuk menemukan sensor mana yang memenuhi kriteria tertentu praktis nol dalam skema multi-tabel, dan dengan demikian alasan untuk pindah ke satu tabel.

Jenis kueri ini dapat dilakukan oleh banyak pengguna secara berurutan karena mereka memilih kelompok data yang berbeda dan membandingkan grafik dari setiap hasil. Sangat frustasi untuk menunggu hampir 10 detik per grafik atau spreadsheet.

Data dibuang setelah 90 hari. Itu bisa diarsipkan tetapi saat ini tidak menjadi persyaratan.

Semoga informasi ini membantu menunjukkan dengan lebih memadai bagaimana data digunakan setelah pengumpulan dan penyimpanan.

JYelton
sumber
Agar pertanyaan ini mendapatkan jawaban yang benar , Anda mungkin harus mengembangkan bagaimana data sebenarnya digunakan. Anda berada di depan kurva pada kedalaman informasi yang Anda berikan sejauh ini tetapi Anda mungkin mengajukan pertanyaan Anda dari sudut yang salah.
Mark Storey-Smith
Poin bagus, @Mark, saya akan menguraikan itu juga. Saya berusaha untuk tidak memiliki pertanyaan terlalu lama karena takut itu akan membanjiri.
JYelton

Jawaban:

5

Anda harus berpikir tentang mempartisi tabel karena alasan besar.

Semua indeks yang Anda miliki di atas meja raksasa, bahkan hanya satu indeks, dapat menghasilkan banyak beban CPU dan I / O disk hanya untuk melakukan pemeliharaan indeks saat menjalankan INSERT, UPDATE, dan HAPUS.

Saya menulis posting sebelumnya pada 7 Oktober 2011 tentang mengapa Pemisahan Tabel akan sangat membantu. Ini satu kutipan dari postingan saya yang lalu:

Partisi data harus berfungsi untuk mengelompokkan data yang secara logis dan kohesif di kelas yang sama. Kinerja pencarian setiap partisi tidak perlu menjadi pertimbangan utama selama data dikelompokkan dengan benar. Setelah Anda mencapai partisi logis, kemudian berkonsentrasi pada waktu pencarian. Jika Anda hanya memisahkan data dengan id saja, mungkin banyak baris data tidak akan pernah diakses untuk dibaca atau ditulis. Sekarang, itu harus menjadi pertimbangan utama: Cari semua id yang paling sering diakses dan dipartisi dengan itu. Semua id yang lebih jarang diakses harus berada di satu tabel arsip besar yang masih dapat diakses dengan pencarian indeks untuk permintaan 'sekali dalam bulan biru'.

Anda dapat membaca seluruh posting saya nanti tentang ini.

Untuk memotong langsung ke pengejaran, Anda perlu meneliti dan mencari tahu data apa yang jarang digunakan dalam tabel 10GB Anda. Data itu harus ditempatkan dalam tabel arsip yang mudah diakses jika Anda membutuhkan pertanyaan adhoc untuk sifat historis. Memigrasi arsip itu dari 10GB, diikuti oleh OPTIMIZE TABLEpada tabel 10GB, dapat menghasilkan Set Kerja yang lebih cepat untuk menjalankan SELECT, INSERT, UPDATE, dan HAPUS. Bahkan DDL akan berjalan lebih cepat pada Perangkat Kerja 2GB daripada tabel 10GB.

UPDATE 2012-02-24 16:19 EDT

Dua hal yang perlu dipertimbangkan

  1. Dari komentar Anda, sepertinya normalisasi adalah apa yang mungkin Anda butuhkan.
  2. Anda mungkin perlu memigrasi semua yang berusia lebih dari 90 hari ke dalam tabel arsip tetapi masih mengakses arsip dan kumpulan kerja pada saat yang sama. Jika semua data Anda adalah MyISAM, saya sarankan menggunakan mesin penyimpanan MERGE. Pertama, Anda membuat peta tabel MERGE sekali yang menyatukan set tabel MyISAM yang berfungsi dan arsip tabel MyISAM. Anda akan menyimpan data kurang dari 91 hari dalam satu tabel MyISAM dan memasukkan data apa pun yang berumur lebih dari 90 hari ke dalam arsip. Anda akan meminta peta tabel MERGE saja.

Berikut adalah dua posting yang saya buat tentang cara menggunakannya:

Ini adalah postingan tambahan yang saya buat di atas meja dengan banyak kolom

Terlalu banyak kolom di MySQL

RolandoMySQLDBA
sumber
Ada kolom yang lebih jarang dibutuhkan, tetapi semua sensor menerima persentase perhatian yang sama. Jadi, saya bisa membayangkan membagi tabel secara vertikal akan menguntungkan. Misalnya, tabel 20 kolom (sering diakses) dan tabel 80 kolom (jarang diakses). Saya tidak yakin ini sama dengan mempartisi.
JYelton
Terima kasih atas hasil editnya. Saya membaca posting Anda tentang "Terlalu banyak kolom di MySQL." Saya akan mengedit pertanyaan saya dengan beberapa poin tambahan yang mungkin berguna.
JYelton
5

Menarik ... Jika semua sensor menghasilkan jenis data yang sama, masuk akal untuk menempatkan semuanya di tabel yang sama, tetapi dengan jumlah data itu, saya dapat melihat mengapa Anda khawatir tentang kinerja.

Apakah 90 hari jumlah waktu yang biasa Anda menghasilkan grafik? Jika demikian, Anda dapat memiliki dua tabel: tabel data sensor utama yang menyimpan data dari 90 (atau sedikit lebih jika Anda menginginkan beberapa kelonggaran) hari yang lalu hingga hari ini, dan semua yang lebih tua dari yang ada dalam tabel arsip. Itu bisa membantu mengurangi ukuran tabel dari mana laporan mulai dihasilkan, dan mudah-mudahan sebagian besar data 10 GB Anda akan ada di tabel arsip, dan bukan di tabel utama. Pekerjaan pengarsipan dapat dijadwalkan untuk berjalan setiap malam.

Mungkin juga mempertimbangkan membangun database pelaporan terpisah yang menyimpan data dalam struktur yang lebih baik untuk menghasilkan laporan dari (tabel yang dirancang untuk lebih mencocokkan dengan apa yang Anda query, dan mungkin pra-kalkulasi dan nilai agregat yang seharusnya memerlukan waktu lama untuk menghasilkan, jika mungkin), dan mengisi kembali dari basis data utama secara teratur (seperti setiap malam). Tentu saja, jika Anda membutuhkan laporan yang dihasilkan dari data terbaru, ini mungkin tidak berfungsi dengan baik.

FrustratedWithFormsDesigner
sumber
Menyimpan apa pun yang melewati 90 hari pada saat ini tidak perlu tetapi akan menyenangkan. Saya setuju yang terbaik untuk menyimpan di tabel "arsip". Grafik dan analisis data berkisar dari sekadar jam hingga 90 hari penuh. Sebagian besar permintaan grafik hanya menggunakan data minggu lalu, tetapi grafik 90 hari adalah umum. Perusahaan kami belum (belum) meminta laporan yang lebih lama.
JYelton
@JYelton: Anda bisa memiliki banyak tingkatan dalam pendekatan ini seperti yang Anda inginkan. Tabel terbaru dapat dimiliki hanya dari Hari ini. Tabel selanjutnya bisa dari hari ini hingga 2 minggu yang lalu. Tabel selanjutnya bisa dari Hari ini hingga 90 hari yang lalu. Meja terakhir bisa SEMUA Segalanya.
FrustratedWithFormsDesigner
Jika saya mengerti Anda dengan benar, Anda mengatakan untuk mereplikasi tabel, tetapi dengan cakupan periode waktu yang berbeda. Jadi, jika seseorang meminta laporan 7 hari, sebuah tabel yang hanya berlaku seminggu akan digunakan. Jika kemudian berkembang hingga 8 hari, tabel terbesar berikutnya (mis. 30 hari) akan digunakan? Ini tentu saja akan meningkatkan kecepatan permintaan berdurasi lebih pendek, tetapi dengan biaya penyimpanan (murah) dan logika pemrograman untuk menangani tabel berjenjang (tidak semurah).
JYelton
@JYelton: Ya, saya pikir Anda memahaminya dengan benar. Jika rentang jangka waktu kueri adalah standar (hari ini - 1 hari, hari ini - 7 hari, hari ini - 30 hari, hari ini - 90 hari) maka saya tidak berpikir itu akan terlalu sulit karena Anda akan selalu tahu tabel mana yang harus memukul. Jika rentang waktu bisa panjang bervariasi di mana awal rentang mungkin bukan tanggal saat ini, maka Anda benar logika untuk menerapkan akan menjadi rumit dan kueri yang lintas tabel bisa menjadi mahal dengan operasi UNION di beberapa tabel.
FrustratedWithFormsDesigner