Mevcut yıl hariç tüm arşivlemenin ve masayı aynı anda bölmenin en iyi yolu nedir?


23

Görev

Bir grup büyük masadan 13 aylık bir dönem dışında hepsini arşivleyin. Arşivlenen veriler başka bir veritabanında saklanmalıdır.

  • Veritabanı basit kurtarma modunda
  • Tablolar 50 mil ile birkaç milyar arasındadır ve bazı durumlarda yüzlerce gb alır.
  • Tablolar şu anda bölümlenmemiş
  • Her tablonun gittikçe artan bir tarih sütununda kümelenmiş bir dizini vardır
  • Her tablo ayrıca, kümelenmemiş bir dizine sahiptir
  • Tablolardaki tüm veri değişiklikleri eklerdir
  • Amaç, birincil veritabanının çalışmama süresini en aza indirmektir.
  • Sunucu 2008 R2 Kuruluşudur

"Arşiv" masası yaklaşık 1.1 milyar sıraya, "canlı" tablo ise yaklaşık 400 milyon olacaktır. Açıkçası, arşiv masası zamanla artacaktır, ancak canlı masanın da oldukça hızlı bir şekilde artmasını bekliyorum. Önümüzdeki birkaç yıl içinde en az% 50 deyin.

Azure veri tabanları hakkında düşünmüştüm ama maalesef 2008 R2'deyiz ve bir süre orada kalacağız.

Mevcut Plan

  • Yeni bir veritabanı oluştur
  • Yeni veritabanında aya göre (değiştirilmiş tarihi kullanarak) bölümlenmiş yeni tablolar oluşturun.
  • En son 12-13 aylık verileri bölümlenmiş tablolara taşıyın.
  • İki veritabanının takas ismini değiştir
  • Taşınan verileri şimdi "arşiv" veritabanından silin.
  • "Arşiv" veritabanındaki tabloların her birini bölümlere ayırın.
  • Gelecekte verileri arşivlemek için bölüm takaslarını kullanın.
    • Arşivlenecek verileri yerinden çıkarmak, o masayı arşiv veritabanına kopyalamak ve sonra arşiv masasına değiştirmek zorunda kalacağımın farkındayım. Bu kabul edilebilir.

Sorun: Verileri ilk bölümlenmiş tablolara taşımaya çalışıyorum (aslında hala üzerinde bir konsept kanıtı yapıyorum). TF 610 ( Veri Yükleme Performansı Kılavuzu'na göre ) ve INSERT...SELECTverileri başlangıçta en az günlüğe kaydedileceğini düşünerek taşımak için bir ifade kullanmaya çalışıyorum . Ne yazık ki her denediğimde tamamen giriş yapıyor.

Bu noktada en iyisi, bir SSIS paketi kullanarak verileri taşımak olabilir. Bundan kaçınmaya çalışıyorum çünkü 200 tablo ile çalışıyorum ve senaryo ile yapabildiğim her şeyi kolayca oluşturabiliyorum ve çalıştırabiliyorum.

Genel planımda eksik olan bir şey var mı ve SSIS, verileri hızlı bir şekilde ve günlüğün en az kullanımıyla (alan endişeleriyle) taşımak için en iyi bahisüm mü?

Veri içermeyen demo kodu

-- 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

Kodu taşı

USE Audit_New
GO
DBCC TRACEON(610);

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

RE "verileri taşı ": Günlük kullanımını en aza indirmek için verileri toplu olarak taşıyabilirsiniz, örneğin dba.stackexchange.com/a/139009/94130 . Bölümleme konusunda bölümlenmiş görüşleri düşündünüz mü?
Alex,

@Alex Yea, ikisini de düşündüm. Yedekleme planım, verileri SSIS kullanarak gruplar halinde taşımak. Ve bu özel durum için benim sorunum tam olarak hangi bölüm için inşa edilmiştir. (hızlı anahtarlama kullanarak veri yükleme / boşaltma)
Kenneth Fisher 12

Yanıtlar:


10

Neden az günlük kaydı alamıyorsunuz?

Referans verdiğiniz Veri Yükleme Performansı Kılavuzunu son derece değerli bir kaynak olarak buldum . Ancak, aynı zamanda% 100 kapsamlı değildir ve kılavuzun zaten yazarın Table Partitioningekleri alan tablonun bölümlenip bölümlendirilmemesine bağlı olarak davranış farklılıklarını gidermek için bir sütun eklememesi için yeterince karmaşık olduğundan şüpheleniyorum . Daha sonra göreceğimiz gibi, tablonun zaten bölümlenmiş olduğu gerçeği, asgari günlük kaydı engelliyor görünmektedir.

görüntü tanımını buraya girin

Önerilen yaklaşım

Veri Yükleme Performansı Kılavuzu'ndaki önerilere ("Bölümlenmiş Bir Tabloyu Toplu Yükleme" bölümü de dahil olmak üzere) ve onlarla milyarlarca satır içeren bölümlenmiş tabloları yükleme deneyimine dayanarak, size önereceğim yaklaşım:

  • Yeni bir veritabanı oluşturun.
  • Yeni veritabanında aylara göre bölümlenmiş yeni tablolar oluşturun.
  • En son veri yılını aşağıdaki şekilde taşıyın:
    • Her ay için yeni bir yığın tablosu oluşturun;
    • TABLOCK ipucunu kullanarak o aydaki verileri yığına ekleyin;
    • Kümelenmiş dizini, bu ayın verilerini içeren öbeğe ekleyin;
    • Tablonun bu ayın verilerini içermesini zorunlu kılan kontrol kısıtlamasını ekleyin;
    • Tabloyu, yeni genel bölümlenmiş tablonun karşılık gelen bölümüne yerleştirin.
  • İki veritabanının takas adını değiştirin.
  • Şimdi "arşiv" veritabanındaki verileri kesin.
  • "Arşiv" veritabanındaki tabloların her birini bölümlere ayırın.
  • Gelecekte verileri arşivlemek için bölüm takaslarını kullanın.

Orijinal yaklaşımınıza göre farklar:

  • Son 12-13 aylık verilerin taşınması metodolojisi TABLOCK, verileri bölümlenmiş tabloya yerleştirmek için bölüm değiştirme özelliğini kullanarak bir seferde bir aylık bir yığına yüklerseniz çok daha etkili olacaktır .
  • DELETEEski tabloyu temizlemek için A tamamen günlüğe kaydedilir. Belki TRUNCATEmasayı ya bırakabilir ya da yeni bir arşiv masası yaratabilirsiniz.

Son veri yılını taşımak için yaklaşımların karşılaştırılması

Makinemdeki yaklaşımları makul bir sürede karşılaştırmak için 100MM rowoluşturduğum ve şemalarını izleyen bir test veri seti kullandım.

Aşağıdaki sonuçlardan da anlaşılacağı gibi, TABLOCKipucu kullanarak bir yığına veri yükleyerek kayıt yazmalarında büyük bir performans artışı ve azalma var . Bu, bir kerede bir bölüm yapılırsa ek bir fayda var. Aynı anda birden fazla bölüm çalıştırırsanız, her seferinde bir bölümleme yönteminin kolayca paralelleştirilebileceğini de unutmayın. Donanımınıza bağlı olarak, bu güzel bir destek verebilir; Sunucu sınıfı donanıma genellikle en az dört bölüm bir defada yükleriz.

görüntü tanımını buraya girin

İşte tam test betiği .

Final notları

Bu sonuçların tümü, bir dereceye kadar donanımınıza bağlıdır. Ancak testlerim dönen disk sürücülü standart dört çekirdekli bir dizüstü bilgisayarda yapıldı. Bu işlemi yürütürken çok fazla başka bir yükü olmayan düzgün bir sunucu kullanıyorsanız, veri yüklerinin daha hızlı olması muhtemeldir.

Örneğin, önerilen yaklaşımı gerçek bir dev sunucuda (Dell R720) çalıştırdım ve 76 seconds( 156 secondsdizüstü bilgisayarımda) bir azalma gördüm . İlginç bir şekilde, bölümlenmiş bir tabloya yerleştirmenin orijinal yaklaşımı aynı iyileşmeyi yaşamamış ve yine 12 minutesde dev sunucu üzerinde çalışmaya devam etmiştir. Muhtemelen bunun nedeni, bu desenin seri yürütme planı vermesi ve dizüstü bilgisayarımdaki tek bir işlemcinin dev sunucudaki tek bir işlemciyle eşleşmesi olabilir.


Tekrar teşekkürler Geoff. SWITCH yöntemini kullanıyorum. Özellikle 13 ay paralel olarak çalıştırmak için SSIS ve dinamik SQL kullanıyorum.
Kenneth Fisher

1

Bu, Biml için iyi bir aday olabilir. Bir yaklaşım, For For her bir konteyner için küçük tarih aralıklarında tek bir tablonun verilerini geçiren yeniden kullanılabilir bir şablon oluşturmak olacaktır. Her bir hak kazanan tablo için aynı paketleri oluşturmak üzere, Biml tablo koleksiyonunuzda dolaşacaktır. Andy Leonard'ın Merdiven Serisinde bir tanıtımı var .


0

Belki, yeni veritabanını oluşturmak yerine, gerçek veritabanını yeni bir veritabanına geri yükleyin ve en yeni 12-13 aylık verileri silin. Ardından, gerçek veritabanınızda, yeni oluşturduğunuz arşiv alanında bulunmayan verileri silin. Büyük silmeler bir sorunsa, bunu yapmak için 10K veya daha büyük setleri komut dosyasıyla silebilirsiniz.

Bölümleme görevleriniz engellenecek gibi görünmüyor ve silme işlemlerinden sonra her iki veritabanına da uygulanabilir gibi görünüyor.


Bunu daha önce küçük veritabanlarıyla yaptım. Geçerli boyut ve ben bu yöntem aslında (min akım DB boyutunu çift) daha uzun ve biraz daha fazla yer alacağını düşünüyorum her iki tarafta bölümlenmiş tablolar ile bitirmek istiyorum gerçeğini göz önüne alındığında
Kenneth Fisher
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.