Bagaimana cara mengelola 3,1 miliar baris data?

14

Saat ini saya ditugaskan mengimplementasikan skema penyimpanan untuk jumlah data yang relatif besar. Data terutama akan diakses untuk menentukan data pointnilai saat ini , tetapi saya juga diharuskan untuk melacak sejarah enam bulan terakhir untuk tren / analisis data.

Persyaratan terbaru ditambahkan untuk melacak nilai min/ max/ sumselama satu jam terakhir.

CATATAN: Idealnya, saya ingin mempertimbangkan opsi MongoDB, tetapi saya perlu menunjukkan bahwa saya telah menghabiskan opsi SQL-Server terlebih dahulu.

Data

Tabel berikut ini menunjukkan sumber data primer (paling sering ditanyakan). Tabel akan memiliki sekitar lima juta baris. Perubahan data sebagian besar akan menjadi UPDATEpernyataan dengan pernyataan yang sangat sesekali INSERTsetelah memuat data awal. Saya telah memilih untuk mengelompokkan data dataPointIdkarena Anda akan selalu memilih all values for a given data point.

// Simplified Table
CREATE TABLE [dbo].[DataPointValue](
    [dataPointId]  [int] NOT NULL,
    [valueId]      [int] NOT NULL,
    [timestamp]    [datetime] NOT NULL,
    [minimum]      [decimal](18, 0) NOT NULL,
    [hourMinimum]  [decimal](18, 0) NOT NULL,
    [current]      [decimal](18, 0) NOT NULL,
    [currentTrend] [decimal](18, 0) NOT NULL,
    [hourMaximum]  [decimal](18, 0) NOT NULL,
    [maximum]      [decimal](18, 0) NOT NULL

    CONSTRAINT [PK_MeterDataPointValue] PRIMARY KEY CLUSTERED ([dataPointId],[valueId])
)

Tabel kedua terutama lebih besar di sekitar 3,1 miliar baris (mewakili data enam bulan terakhir). Data yang lebih tua dari enam bulan akan dibersihkan; jika tidak secara ketat INSERTpernyataan data (~ 200 baris / detik, 720.000 baris / jam, 17 juta baris / minggu).

// Simplified Table
CREATE TABLE [dbo].[DataPointValueHistory](
    [dataPointId] [int]            NOT NULL,
    [valueId]     [int]            NOT NULL,
    [timestamp]   [datetime]       NOT NULL,
    [value]       [decimal](18, 0) NOT NULL,
    [delta]       [decimal](18, 0) NOT NULL

    CONSTRAINT [PK_MeterDataPointHistory] PRIMARY KEY CLUSTERED ([dataPointId], [valueId], [timestamp])

)

Harapannya adalah bahwa tabel ini akan berlipat ganda karena jumlah nilai titik data yang dilacak meningkat menjadi 400 baris / detik (sehingga mencapai ~ 10 miliar tidak keluar dari pertanyaan).

Pertanyaannya ( ya, saya bertanya lebih dari satu ... semuanya terkait erat).

Saat ini saya menggunakan database SQL-Server 2008 R2 Standard Edition. Saya mungkin akan menjelaskan tentang peningkatan ke Enterprise Edition jika dapat memperoleh tingkat kinerja yang diinginkan dengan partisi tabel (atau MongoDB jika tidak dapat mencapai tingkat kinerja yang diperlukan dengan SQL-Server). Saya ingin masukan Anda tentang hal berikut:


1) Mengingat bahwa saya perlu menghitung min, maxdan sumselama satu jam terakhir (seperti dalam now - 60 minutes). Apa pendekatan terbaik untuk melacak data terbaru:

  • Simpan data terbaru dalam memori layanan data. Tuliskan min / maks / rata-rata yang dihitung dengan masing-masing UPDATE data.

  • Permintaan riwayat terbaru dari tabel riwayat (dampak pertanyaan selanjutnya?) Selama setiap pernyataan UPDATE. Kueri akan mengakses data terbaru untuk nilai titik data dan hanya boleh memindai lebih dari satu juta catatan terakhir?

  • Simpan riwayat terbaru di baris DataPointValue untuk menghindari pencarian tabel riwayat? Mungkin disimpan sebagai string yang dibatasi dan diproses di dalam proc UPDATE?

  • Opsi lain yang belum saya pertimbangkan?


2) Untuk DataPointValueHistory, permintaan terhadap data akan selalu oleh dataPointIddan satu atau lebih valueId. Data yang ditanyakan biasanya untuk hari terakhir, minggu atau bulan, tetapi mungkin untuk enam bulan penuh dalam beberapa kasus.

Saat ini saya membuat set data sampel untuk bereksperimen dengan apakah lebih masuk akal untuk mengelompokkan berdasarkan dataPointId / valueId / timeStamp atau timeStamp / dataPointId / valueId. Jika ada yang punya pengalaman berurusan dengan meja sebesar ini dan bersedia menawarkan wawasan mereka, itu akan dihargai. Saya condong ke opsi terakhir untuk menghindari fragmentasi indeks, tetapi kinerja permintaan sangat penting.

  • Cluster DataPointValueHistoryberdasarkan dataPointId -> valueId -> timeStamp

  • Cluster DataPointValueHistoryberdasarkan timeStamp -> dataPointId -> valueId


3) Akhirnya, seperti yang disebutkan di atas, saya pikir akan masuk akal untuk mempartisi DataPointValueHistorytabel. Setiap saran tentang cara terbaik mempartisi data histori akan sangat dihargai.

  • Jika dikelompokkan berdasarkan stempel waktu pertama, saya berpikir bahwa data harus dipartisi berdasarkan minggu (total 27 partisi). Partisi tertua akan dihapus setelah minggu ke 27.

  • Jika dikelompokkan oleh dataPointId pertama, saya berpikir bahwa data harus dipartisi oleh beberapa modulus id?

Karena saya memiliki pengalaman yang sangat terbatas dengan tabel partisi, keahlian Anda akan dihargai.

Calgary Coder
sumber
Apakah Anda menghapus versi pertanyaan ini di StackOverflow?
Taryn
@bluefeet - Ya, itu ditandai sebagai di luar topik ... jadi saya menghapus pertanyaan SO dan menciptakan kembali di sini (saya mungkin harus menunggu untuk dimigrasi).
Calgary Coder
Tidak masalah, saya hanya memastikan kami tidak memiliki pertanyaan lintas-posting.
Taryn
Pada Edisi Standar, Anda masih dapat mempartisi data menggunakan tampilan yang dipartisi dan beberapa tabel dasar. Tidak yakin apakah Anda mempertimbangkannya.
Jon Seigel
@ Jon - Ya, saya telah mempertimbangkan partisi tabel manual (pilihan tertentu akan didasarkan pada apakah ada atau tidak lisensi Enterprise tersedia ... jika ya, mengapa peran saya sendiri).
Calgary Coder

Jawaban: