Pengantar
Beberapa tahun yang lalu kami ditugaskan dengan persyaratan bisnis untuk data kartu dalam format tertentu untuk tujuan sesuatu yang disebut "rekonsiliasi". Idenya adalah untuk menyajikan data dalam tabel ke aplikasi yang akan mengkonsumsi dan memproses data yang akan memiliki periode retensi enam bulan. Kami harus membuat database baru untuk kebutuhan bisnis ini dan kemudian membuat tabel inti sebagai tabel yang dipartisi. Proses yang dijelaskan di sini adalah proses yang kami gunakan untuk memastikan bahwa data yang lebih lama dari enam bulan dipindahkan dari tabel dengan cara yang bersih.
Sedikit Tentang Partisi
Tabel Partisi adalah teknologi database yang memungkinkan Anda untuk menyimpan data milik satu unit logis (tabel) sebagai satu set partisi yang akan duduk di struktur fisik yang terpisah – file data – melalui lapisan abstraksi yang disebut File Groups di SQL Server. Proses pembuatan Tabel Partisi ini melibatkan dua objek utama:
Fungsi Partisi :Fungsi Partisi mendefinisikan bagaimana baris tabel yang dipartisi dipetakan berdasarkan nilai kolom tertentu (Kolom Partisi). Tabel yang dipartisi dapat didasarkan pada daftar atau rentang. Untuk tujuan kasus penggunaan kami (hanya mempertahankan data selama enam bulan), kami menggunakan Partisi Rentang . Fungsi Partisi dapat didefinisikan sebagai RANGE RIGHT atau RANGE LEFT. Kami menggunakan RANGE RIGHT seperti yang ditunjukkan pada kode di Listing 1 yang berarti nilai batas akan berada di sisi kanan interval nilai batas ketika nilai diurutkan dalam urutan menaik dari kiri ke kanan.
-- Listing 1: Create a Partition Function USE [post_office_history] GO CREATE PARTITION FUNCTION PostTranPartFunc (datetime) AS RANGE RIGHT FOR VALUES ('20190201' ,'20190301' ,'20190401' ,'20190501' ,'20190601' ,'20190701' ,'20190801' ,'20190901' ,'20191001' ,'20191101' ,'20191201' ) GO
Skema Partisi :Skema partisi didasarkan pada Fungsi Partisi dan menentukan di mana baris struktur fisik milik setiap partisi akan ditempatkan. Ini dicapai dengan memetakan baris seperti itu ke grup file. Daftar 2 menunjukkan kode untuk membuat Skema Partisi. Sebelum membuat Skema Partisi, grup file yang akan dirujuk harus ada.
-- Listing 2: Create Partition Scheme -- -- Step 1: Create Filegroups -- USE [master] GO ALTER DATABASE [post_office_history] ADD FILEGROUP [JAN] ALTER DATABASE [post_office_history] ADD FILEGROUP [FEB] ALTER DATABASE [post_office_history] ADD FILEGROUP [MAR] ALTER DATABASE [post_office_history] ADD FILEGROUP [APR] ALTER DATABASE [post_office_history] ADD FILEGROUP [MAY] ALTER DATABASE [post_office_history] ADD FILEGROUP [JUN] ALTER DATABASE [post_office_history] ADD FILEGROUP [JUL] ALTER DATABASE [post_office_history] ADD FILEGROUP [AUG] ALTER DATABASE [post_office_history] ADD FILEGROUP [SEP] ALTER DATABASE [post_office_history] ADD FILEGROUP [OCT] ALTER DATABASE [post_office_history] ADD FILEGROUP [NOV] ALTER DATABASE [post_office_history] ADD FILEGROUP [DEC] GO -- Step 2: Add Data Files to each Filegroup -- USE [master] GO ALTER DATABASE [post_office_history] ADD FILE (NAME = N'post_office_history_part_01', FILENAME = N'E:\MSSQL\DATA\post_office_history_part_01.ndf', SIZE = 2097152KB, FILEGROWTH = 1048576KB) TO FILEGROUP [JAN] ALTER DATABASE [post_office_history] ADD FILE (NAME = N'post_office_history_part_02', FILENAME = N'E:\MSSQL\DATA\post_office_history_part_02.ndf', SIZE = 2097152KB, FILEGROWTH = 1048576KB) TO FILEGROUP [FEB] ALTER DATABASE [post_office_history] ADD FILE (NAME = N'post_office_history_part_03', FILENAME = N'E:\MSSQL\DATA\post_office_history_part_03.ndf', SIZE = 2097152KB, FILEGROWTH = 1048576KB) TO FILEGROUP [MAR] ALTER DATABASE [post_office_history] ADD FILE (NAME = N'post_office_history_part_04', FILENAME = N'E:\MSSQL\DATA\post_office_history_part_04.ndf', SIZE = 2097152KB, FILEGROWTH = 1048576KB) TO FILEGROUP [APR] ALTER DATABASE [post_office_history] ADD FILE (NAME = N'post_office_history_part_05', FILENAME = N'E:\MSSQL\DATA\post_office_history_part_05.ndf', SIZE = 2097152KB, FILEGROWTH = 1048576KB) TO FILEGROUP [MAY] ALTER DATABASE [post_office_history] ADD FILE (NAME = N'post_office_history_part_06', FILENAME = N'G:\MSSQL\DATA\post_office_history_part_06.ndf', SIZE = 2097152KB, FILEGROWTH = 1048576KB) TO FILEGROUP [JUN] ALTER DATABASE [post_office_history] ADD FILE (NAME = N'post_office_history_part_07', FILENAME = N'G:\MSSQL\DATA\post_office_history_part_07.ndf', SIZE = 2097152KB, FILEGROWTH = 1048576KB) TO FILEGROUP [JUL] ALTER DATABASE [post_office_history] ADD FILE (NAME = N'post_office_history_part_08', FILENAME = N'G:\MSSQL\DATA\post_office_history_part_08.ndf', SIZE = 2097152KB, FILEGROWTH = 1048576KB) TO FILEGROUP [AUG] ALTER DATABASE [post_office_history] ADD FILE (NAME = N'post_office_history_part_09', FILENAME = N'G:\MSSQL\DATA\post_office_history_part_09.ndf', SIZE = 2097152KB, FILEGROWTH = 1048576KB) TO FILEGROUP [SEP] ALTER DATABASE [post_office_history] ADD FILE (NAME = N'post_office_history_part_10', FILENAME = N'G:\MSSQL\DATA\post_office_history_part_10.ndf', SIZE = 2097152KB, FILEGROWTH = 1048576KB) TO FILEGROUP [OCT] GO ALTER DATABASE [post_office_history] ADD FILE (NAME = N'post_office_history_part_09', FILENAME = N'G:\MSSQL\DATA\post_office_history_part_11.ndf', SIZE = 2097152KB, FILEGROWTH = 1048576KB) TO FILEGROUP [NOV] ALTER DATABASE [post_office_history] ADD FILE (NAME = N'post_office_history_part_10', FILENAME = N'G:\MSSQL\DATA\post_office_history_part_12.ndf', SIZE = 2097152KB, FILEGROWTH = 1048576KB) TO FILEGROUP [DEC] GO -- Step 3: Create Partition Scheme -- PRINT 'creating partition scheme ...' GO USE [post_office_history] GO CREATE PARTITION SCHEME PostTranPartSch AS PARTITION PostTranPartFunc TO ( JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC ) GO
Perhatikan bahwa untuk N partisi, akan selalu ada N-1 batasan. Kehati-hatian harus diambil ketika mendefinisikan Filegroup pertama dalam Skema Partisi. Batas pertama yang tercantum dalam Fungsi Partisi akan terletak di antara Filegroups pertama dan kedua sehingga nilai batas ini (20190201) akan berada di partisi kedua (FEB). Selain itu, sebenarnya dimungkinkan untuk menempatkan semua partisi dalam satu filegroup tetapi kami telah memilih filegroup yang terpisah dalam kasus ini.
Membuat Tangan Kita Kotor
Jadi, mari selami tugas mengganti partisi!
Hal pertama yang perlu kita lakukan adalah menentukan dengan tepat bagaimana data kita didistribusikan di antara partisi sehingga kita dapat mengetahui partisi mana yang ingin kita alihkan. Biasanya kita akan mengganti partisi terlama.
-- Listing 3: Check Data Distribution in Partitions -- USE POST_OFFICE_HISTORY GO SELECT $PARTITION.POSTTRANPARTFUNC(DATETIME_TRAN_LOCAL) AS [PARTITION NUMBER] , MIN(DATETIME_TRAN_LOCAL) AS [MIN DATE] , MAX(DATETIME_TRAN_LOCAL) AS [MAX DATE] , COUNT(*) AS [ROWS IN PARTITION] FROM DBO.POST_TRAN_TAB -- PARTITIONED TABLE GROUP BY $PARTITION.POSTTRANPARTFUNC(DATETIME_TRAN_LOCAL) ORDER BY [PARTITION NUMBER] GO
Gbr. 1 Output Listing 3
Gambar 1 menunjukkan kepada kita output dari kueri di Listing 3. Partisi tertua adalah Partisi 2 yang berisi baris dari tahun 2017. Kami memverifikasi ini dengan kueri di Listing 4. Listing 4 juga menunjukkan kepada kita Filegroup mana yang menyimpan data di Partisi 2.
-- Listing 4: Check Filegroup Associated with Partition -- USE POST_OFFICE_HISTORY GO SELECT PS.NAME AS PSNAME, DDS.DESTINATION_ID AS PARTITIONNUMBER, FG.NAME AS FILEGROUPNAME FROM (((SYS.TABLES AS T INNER JOIN SYS.INDEXES AS I ON (T.OBJECT_ID = I.OBJECT_ID)) INNER JOIN SYS.PARTITION_SCHEMES AS PS ON (I.DATA_SPACE_ID = PS.DATA_SPACE_ID)) INNER JOIN SYS.DESTINATION_DATA_SPACES AS DDS ON (PS.DATA_SPACE_ID = DDS.PARTITION_SCHEME_ID)) INNER JOIN SYS.FILEGROUPS AS FG ON DDS.DATA_SPACE_ID = FG.DATA_SPACE_ID WHERE (T.NAME = 'POST_TRAN_TAB') AND (I.INDEX_ID IN (0,1)) AND DDS.DESTINATION_ID = $PARTITION.POSTTRANPARTFUNC('20171108') ;
Gbr. 1 Output Listing 3
Gambar 2 Output Listing 4
Daftar 4 menunjukkan kepada kita bahwa filegroup yang terkait dengan Partisi 2 adalah NOV . Untuk mematikan Partisi 2, kita memerlukan tabel histori yang merupakan replika dari tabel langsung tetapi berada di grup file yang sama dengan partisi yang ingin kita alihkan. Karena kita sudah memiliki tabel ini, yang kita butuhkan hanyalah membuatnya kembali di Filegroup yang diinginkan. Anda juga perlu membuat ulang indeks berkerumun. Perhatikan bahwa indeks berkerumun ini memiliki definisi yang sama dengan indeks berkerumun pada tabel post_tran_tab dan juga berada di grup file yang sama dengan post_tran_tab_hist tabel.
-- Listing 5: Re-create the History Table -- Re-create the History Table -- USE [post_office_history] GO SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO SET ANSI_PADDING ON GO DROP TABLE [dbo].[post_tran_tab_hist] GO CREATE TABLE [dbo].[post_tran_tab_hist]( [tran_nr] [bigint] NOT NULL, [tran_type] [char](2) NULL, [tran_reversed] [char](2) NULL, [batch_nr] [int] NULL, [message_type] [char](4) NULL, [source_node_name] [varchar](12) NULL, [system_trace_audit_nr] [char](6) NULL, [settle_currency_code] [char](3) NULL, [sink_node_name] [varchar](30) NULL, [sink_node_currency_code] [char](3) NULL, [to_account_id] [varchar](30) NULL, [pan] [varchar](19) NOT NULL, [pan_encrypted] [char](18) NULL, [pan_reference] [char](70) NULL, [datetime_tran_local] [datetime] NOT NULL, [tran_amount_req] [float] NOT NULL, [tran_amount_rsp] [float] NOT NULL, [tran_cash_req] [float] NOT NULL, [tran_cash_rsp] [float] NOT NULL, [datetime_tran_gmt] [char](10) NULL, [merchant_type] [char](4) NULL, [pos_entry_mode] [char](3) NULL, [pos_condition_code] [char](2) NULL, [acquiring_inst_id_code] [varchar](11) NULL, [retrieval_reference_nr] [char](12) NULL, [auth_id_rsp] [char](6) NULL, [rsp_code_rsp] [char](2) NULL, [service_restriction_code] [char](3) NULL, [terminal_id] [char](8) NULL, [terminal_owner] [varchar](25) NULL, [card_acceptor_id_code] [char](15) NULL, [card_acceptor_name_loc] [char](40) NULL, [from_account_id] [varchar](28) NULL, [auth_reason] [char](1) NULL, [auth_type] [char](1) NULL, [message_reason_code] [char](4) NULL, [datetime_req] [datetime] NULL, [datetime_rsp] [datetime] NULL, [from_account_type] [char](2) NULL, [to_account_type] [char](2) NULL, [insert_date] [datetime] NOT NULL, [tran_postilion_originated] [int] NOT NULL, [card_product] [varchar](20) NULL, [card_seq_nr] [char](3) NULL, [expiry_date] [char](4) NULL, [srcnode_cash_approved] [float] NOT NULL, [tran_completed] [char](2) NULL ) ON [NOV] GO SET ANSI_PADDING OFF GO -- Re-create the Clustered Index -- USE [post_office_history] GO CREATE CLUSTERED INDEX [IX_Datetime_Local] ON [dbo].[post_tran_tab_hist] ( [datetime_tran_local] ASC, [tran_nr] ASC ) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [NOV] GO
Mengganti partisi terakhir sekarang menjadi perintah satu baris. Menghitung kedua tabel sebelum dan sesudah menjalankan perintah satu baris ini akan memberikan jaminan bahwa kita memiliki semua data yang diinginkan.
Gbr. 3 Tabel post_tran_tab_hist berada di NOV Filegroup
-- Listing 6: Switching Out the Last Partition SELECT COUNT(*) FROM 'POST_TRAN_TAB'; SELECT COUNT(*) FROM 'POST_TRAN_TAB_HIST'; USE [POST_OFFICE_HISTORY] GO ALTER TABLE POST_TRAN_TAB SWITCH PARTITION 2 TO POST_TRAN_TAB_HIST GO SELECT COUNT(*) FROM 'POST_TRAN_TAB'; SELECT COUNT(*) FROM 'POST_TRAN_TAB_HIST';
Karena kami telah mengganti partisi terakhir, kami tidak lagi membutuhkan batas. Kami menggabungkan dua rentang yang sebelumnya dipisahkan oleh batas itu menggunakan perintah di Listing 7. Kami selanjutnya memotong tabel histori seperti yang ditunjukkan pada Listing 8. Kami melakukan ini karena inilah intinya:menghapus data lama yang tidak lagi kami perlukan.
-- Listing 7: Merging Partition Ranges -- Merge Range USE [POST_OFFICE_HISTORY] GO ALTER PARTITION FUNCTION POSTTRANPARTFUNC() MERGE RANGE ('20171101'); -- Confirm Range Is Merged USE [POST_OFFICE_HISTORY] GO SELECT * FROM SYS.PARTITION_RANGE_VALUES GO>
Gambar 4 Batas Digabung
-- Listing 8: Truncate the History Table USE [post_office_history] GO TRUNCATE TABLE post_tran_tab_hist; GO
Gbr. 5 Jumlah Baris untuk Kedua Tabel sebelum Dipotong
Perhatikan bahwa jumlah baris dalam tabel riwayat sama persis dengan jumlah baris sebelumnya di Partisi 2 seperti yang ditunjukkan pada Gambar 1. Anda juga dapat bekerja ekstra dengan memulihkan ruang kosong di grup file milik yang terakhir partisi. Ini akan berguna jika karena Anda membutuhkan ruang ini untuk data baru yang akan berada di partisi sebelumnya. Langkah ini mungkin tidak diperlukan jika Anda merasa memiliki cukup ruang di lingkungan Anda.
-- Listing 9: Recover Space on Operating System -- Determine that File has been emptied USE [post_office_history] GO SELECT DF.FILE_ID, DF.NAME, DF.PHYSICAL_NAME, DS.NAME, DS.TYPE, DF.STATE_DESC FROM SYS.DATABASE_FILES DF JOIN SYS.DATA_SPACES DS ON DF.DATA_SPACE_ID = DS.DATA_SPACE_ID;
Gambar 7 Pemetaan File ke Filegroup
-- Shrink the file to 2GB USE [post_office_history] GO DBCC SHRINKFILE (N'post_office_history_part_11’, 2048) GO -- From the OS confirm free space on disks SELECT DISTINCT DB_NAME (S.DATABASE_ID) AS DATABASE_NAME, S.DATABASE_ID, S.VOLUME_MOUNT_POINT --, S.VOLUME_ID , S.LOGICAL_VOLUME_NAME , S.FILE_SYSTEM_TYPE , S.TOTAL_BYTES/1024/1024/1024 AS [TOTAL_SIZE (GB)] , S.AVAILABLE_BYTES/1024/1024/1024 AS [FREE_SPACE (GB)] , LEFT ((ROUND (((S.AVAILABLE_BYTES*1.0)/S.TOTAL_BYTES), 4)*100),4) AS PERCENT_FREE FROM SYS.MASTER_FILES AS F CROSS APPLY SYS.DM_OS_VOLUME_STATS (F.DATABASE_ID, F.FILE_ID) AS S WHERE DB_NAME (S.DATABASE_ID) = 'POST_OFFICE_HISTORY';
Gbr. 8 Ruang Kosong pada Sistem Operasi
Kesimpulan
Pada artikel ini, kami telah melakukan penelusuran proses untuk mengganti partisi dari tabel yang dipartisi. Ini adalah cara yang sangat efisien untuk mengelola pertumbuhan data secara native di SQL Server. Teknologi yang lebih canggih seperti Stretch Database tersedia dalam versi SQL Server saat ini.
Referensi
Isakov, V. (2018). Ref Ujian 70-764 Mengelola Infrastruktur Database SQL. Pendidikan Pearson
Tabel dan Indeks yang Dipartisi di SQL Server