Apa cara terbaik untuk mengarsipkan semua kecuali tahun ini dan mempartisi tabel pada saat yang sama


23

Tugas

Arsipkan semua kecuali periode bergulir 13 bulan dari sekelompok tabel besar. Data yang diarsipkan harus disimpan dalam database lain.

  • Basis data dalam mode pemulihan sederhana
  • Tabelnya adalah 50 mil baris hingga beberapa miliar dan dalam beberapa kasus masing-masing memakan ratusan gb.
  • Tabel saat ini tidak dipartisi
  • Setiap tabel memiliki satu indeks berkerumun di kolom tanggal yang semakin meningkat
  • Setiap tabel juga memiliki satu indeks non-cluster
  • Semua perubahan data pada tabel adalah sisipan
  • Tujuannya adalah untuk meminimalkan downtime dari basis data primer.
  • Server adalah 2008 R2 Enterprise

Tabel "arsip" akan memiliki sekitar 1,1 miliar baris, tabel "langsung" sekitar 400 juta. Jelas tabel arsip akan meningkat seiring waktu, tetapi saya berharap tabel langsung akan meningkat dengan cukup cepat juga. Katakan 50% setidaknya dalam beberapa tahun ke depan.

Saya telah memikirkan tentang peregangan basis data Azure tetapi sayangnya kami berada di 2008 R2 dan cenderung tinggal di sana untuk sementara waktu.

Rencana saat ini

  • Buat database baru
  • Buat tabel baru yang dipartisi berdasarkan bulan (menggunakan tanggal yang dimodifikasi) di database baru.
  • Pindahkan data 12-13 bulan terakhir ke tabel dipartisi.
  • Lakukan pergantian nama dari dua basis data
  • Hapus data yang dipindahkan dari database "arsip" sekarang.
  • Partisi setiap tabel dalam database "arsip".
  • Gunakan swap partisi untuk mengarsipkan data di masa mendatang.
    • Saya menyadari bahwa saya harus menukar data yang akan diarsipkan, menyalin tabel itu ke database arsip, dan kemudian menukarnya ke tabel arsip. Ini bisa diterima.

Masalah: Saya mencoba untuk memindahkan data ke tabel partisi awal (sebenarnya saya masih melakukan pembuktian konsep di atasnya). Saya mencoba menggunakan TF 610 (sesuai dengan Panduan Kinerja Pemuatan Data ) dan INSERT...SELECTpernyataan untuk memindahkan data yang awalnya berpikir itu akan dicatat secara minimal. Sayangnya setiap kali saya mencoba sepenuhnya login.

Pada titik ini saya pikir taruhan terbaik saya adalah memindahkan data menggunakan paket SSIS. Saya mencoba untuk menghindari itu karena saya bekerja dengan 200 tabel dan apa pun yang dapat saya lakukan dengan skrip saya dapat dengan mudah menghasilkan dan menjalankan.

Apakah ada sesuatu yang saya lewatkan dalam rencana umum saya, dan apakah SSIS taruhan terbaik saya untuk memindahkan data dengan cepat dan dengan penggunaan log yang minimal (masalah ruang)?

Kode demo tanpa data

-- Existing structure
USE [Audit]
GO

CREATE TABLE [dbo].[AuditTable](
    [Col1] [bigint] NULL,
    [Col2] [int] NULL,
    [Col3] [int] NULL,
    [Col4] [int] NULL,
    [Col5] [int] NULL,
    [Col6] [money] NULL,
    [Modified] [datetime] NULL,
    [ModifiedBy] [varchar](50) NULL,
    [ModifiedType] [char](1) NULL
); 
-- ~1.4 bill rows, ~20% in the last year

CREATE CLUSTERED INDEX [AuditTable_Modified] ON [dbo].[AuditTable]
(   [Modified] ASC   )
GO


-- New DB & Code
USE Audit_New
GO

CREATE PARTITION FUNCTION ThirteenMonthPartFunction (datetime)
AS RANGE RIGHT FOR VALUES ('20150701', '20150801', '20150901', '20151001', '20151101', '20151201', 
                            '20160101', '20160201', '20160301', '20160401', '20160501', '20160601', 
                            '20160701') 

CREATE PARTITION SCHEME ThirteenMonthPartScheme AS PARTITION ThirteenMonthPartFunction
ALL TO ( [PRIMARY] );

CREATE TABLE [dbo].[AuditTable](
    [Col1] [bigint] NULL,
    [Col2] [int] NULL,
    [Col3] [int] NULL,
    [Col4] [int] NULL,
    [Col5] [int] NULL,
    [Col6] [money] NULL,
    [Modified] [datetime] NULL,
    [ModifiedBy] [varchar](50) NULL,
    [ModifiedType] [char](1) NULL
) ON ThirteenMonthPartScheme (Modified)
GO

CREATE CLUSTERED INDEX [AuditTable_Modified] ON [dbo].[AuditTable]
(
    [Modified] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON ThirteenMonthPartScheme (Modified)
GO

CREATE NONCLUSTERED INDEX [AuditTable_Col1_Col2_Col3_Col4_Modified] ON [dbo].[AuditTable]
(
    [Col1] ASC,
    [Col2] ASC,
    [Col3] ASC,
    [Col4] ASC,
    [Modified] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON ThirteenMonthPartScheme (Modified)
GO

Pindahkan kode

USE Audit_New
GO
DBCC TRACEON(610);

INSERT INTO AuditTable
SELECT * FROM Audit.dbo.AuditTable
WHERE Modified >= '6/1/2015'
ORDER BY Modified

RE "pindahkan data": Untuk meminimalkan penggunaan log, Anda dapat memindahkan data dalam batch misalnya "Approch 2" di dba.stackexchange.com/a/139009/94130 . Mengenai masalah pemartisian, apakah Anda sudah mempertimbangkan tampilan yang dipartisi?
Alex

@ Alex Ya, saya sudah mempertimbangkan keduanya. Paket cadangan saya adalah memindahkan data dalam batch menggunakan SSIS. Dan untuk kasus khusus ini masalah saya adalah untuk apa partisi dibangun. (memuat / membongkar data menggunakan switching)
Kenneth Fisher

Jawaban:


10

Mengapa Anda tidak mendapatkan penebangan minimal?

Saya telah menemukan Panduan Kinerja Pemuatan Data , yang Anda rujuk, sebagai sumber daya yang sangat berharga. Namun, itu juga tidak 100% komprehensif, dan saya menduga bahwa grid sudah cukup kompleks sehingga penulis tidak menambahkan kolom Table Partitioninguntuk memecah perbedaan dalam perilaku tergantung pada apakah tabel yang menerima sisipan dipartisi. Seperti yang akan kita lihat nanti, fakta bahwa tabel sudah dipartisi tampaknya menghambat logging minimum.

masukkan deskripsi gambar di sini

Pendekatan yang disarankan

Berdasarkan rekomendasi dalam Panduan Kinerja Pemuatan Data (termasuk bagian "Memuat Massal Tabel yang Dipartisi") serta pengalaman yang luas memuat tabel yang dipartisi dengan puluhan miliar baris, inilah pendekatan yang akan saya rekomendasikan:

  • Buat database baru.
  • Buat tabel baru yang dipartisi berdasarkan bulan di basis data baru.
  • Pindahkan data tahun terakhir, dengan cara berikut:
    • Untuk setiap bulan, buat tabel tumpukan baru;
    • Masukkan bulan data itu ke tumpukan menggunakan petunjuk TABLOCK;
    • Tambahkan indeks berkerumun ke tumpukan yang berisi bulan data;
    • Tambahkan batasan pemeriksaan yang memaksa bahwa tabel hanya berisi data bulan ini;
    • Ubah tabel menjadi partisi yang sesuai dari tabel dipartisi keseluruhan baru.
  • Lakukan pergantian nama dari dua basis data.
  • Pangkas data dalam database "arsip" sekarang.
  • Partisi setiap tabel dalam database "arsip".
  • Gunakan swap partisi untuk mengarsipkan data di masa mendatang.

Perbedaan jika dibandingkan dengan pendekatan awal Anda:

  • Metodologi memindahkan data 12-13 bulan terakhir akan jauh lebih efisien jika Anda memuat ke tumpukan dengan TABLOCKsatu bulan pada suatu waktu, menggunakan pengalihan partisi untuk menempatkan data ke dalam tabel dipartisi.
  • A DELETEuntuk menghapus tabel lama akan sepenuhnya dicatat. Mungkin Anda bisa TRUNCATEatau menjatuhkan tabel dan membuat tabel arsip baru.

Perbandingan pendekatan untuk memindahkan data tahun terakhir

Untuk membandingkan pendekatan dalam jumlah waktu yang wajar pada mesin saya, saya menggunakan 100MM rowset data uji yang saya hasilkan dan yang mengikuti skema Anda.

Seperti yang Anda lihat dari hasil di bawah ini, ada peningkatan kinerja yang besar dan pengurangan penulisan log dengan memuat data ke tumpukan menggunakan TABLOCKpetunjuk. Ada manfaat tambahan jika ini dilakukan satu partisi pada satu waktu. Perlu juga dicatat bahwa metode satu-partisi-pada-satu dapat dengan mudah diparalelkan jika Anda menjalankan banyak partisi sekaligus. Tergantung pada perangkat keras Anda, itu mungkin menghasilkan dorongan yang bagus; kami biasanya memuat setidaknya empat partisi sekaligus pada perangkat keras kelas server.

masukkan deskripsi gambar di sini

Inilah skrip tes lengkap .

Catatan akhir

Semua hasil ini tergantung pada perangkat keras Anda sampai tingkat tertentu. Namun, pengujian saya dilakukan pada laptop quad-core standar dengan disk drive berputar. Kemungkinan beban data akan jauh lebih cepat jika Anda menggunakan server yang layak yang tidak memiliki banyak beban lain pada saat Anda melakukan proses ini.

Sebagai contoh, saya menjalankan pendekatan yang direkomendasikan pada server dev yang sebenarnya (Dell R720) dan melihat pengurangan ke 76 seconds(dari 156 secondspada laptop saya). Menariknya, pendekatan asli memasukkan ke dalam tabel dipartisi tidak mengalami peningkatan yang sama dan masih mengambil alih 12 minutespada server dev. Mungkin ini karena pola ini menghasilkan rencana eksekusi serial, dan satu prosesor pada laptop saya dapat mencocokkan satu prosesor pada server dev.


Sekali lagi terima kasih Geoff. Saya menggunakan metode SWITCH. Secara khusus saya menggunakan SSIS & SQL dinamis untuk menjalankan 13 bulan secara paralel.
Kenneth Fisher

1

Ini mungkin kandidat yang baik untuk Biml. Salah satu pendekatan adalah membuat templat yang dapat digunakan kembali yang akan memigrasi data untuk satu tabel dalam rentang tanggal kecil dengan wadah Untuk Setiap. Biml akan mengulang-ulang koleksi tabel Anda untuk membuat paket identik untuk setiap tabel kualifikasi. Andy Leonard memiliki intro di Stairway Series-nya .


0

Mungkin, alih-alih membuat database baru, kembalikan database asli ke database baru dan hapus data 12-13 bulan terbaru. Kemudian dalam database asli Anda hapus data yang tidak terkandung dalam area arsip yang baru Anda buat. Jika penghapusan besar merupakan masalah, mungkin Anda bisa menghapus set 10K atau lebih besar dengan cara script untuk melakukannya.

Tugas partisi Anda sepertinya tidak akan terganggu dan tampaknya berlaku untuk basis data setelah penghapusan Anda.


Saya telah melakukannya dengan basis data yang lebih kecil sebelumnya. Mengingat ukuran saat ini dan fakta bahwa saya ingin berakhir dengan tabel dipartisi di kedua sisi saya pikir metode ini sebenarnya akan memakan waktu lebih lama & lebih banyak ruang (gandakan ukuran DB saat ini di min)
Kenneth Fisher
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.