Bir tabloda büyük değişiklikler yapılması için daha iyi olan şey: her seferinde SİL ve INSERT veya mevcut GÜNCELLEME?


27

Günlük olarak bir tabloda 36K kayıt etrafında değişiklik yapmam gereken bir proje yapıyorum. Neyin daha iyi performans göstereceğini merak ediyorum:

  1. satırları sil ve yenilerini ekle, veya
  2. zaten varolan satırları güncelle

Benim için sadece tüm satırları silmek ve yenilerini eklemek daha kolaydır, ancak eğer bu tabloyu ve dizinleri parçalayacak ve performansı etkileyecekse, mümkün olduğunda güncellemeleri yapmayı ve gerektiğinde sadece sil / ekle'yi tercih ederim.

Bu gecelik bir hizmet olacak ve ben sürecin hızını iyileştirmek istemiyorum. 89 milyon kaydımın bulunduğu genel olarak bu tablodaki sorguların performansı ve bu gece işleminin onu nasıl etkileyeceği hakkında daha çok endişeliyim.

Kayıtları silmeli / eklemeli miyim yoksa bu gecelik işlem için var olanları (mümkünse) güncellemeli miyim?


Sanırım alanlarınızdaki indekslerin potansiyel varlığına bağlı olacağı için masanız hakkında daha fazla ayrıntı vermeniz gerektiğine inanıyorum.
SRKX

Yanıtlar:


9

Bu gerçekten verilerin ne kadar değiştiğine bağlı. Diyelim ki bu tablonun 20 sütunu var. Ve ayrıca 5 endeksiniz var - her biri farklı. sütunu.

Şimdi, 20 sütundaki değerlerin tümü değişiyorsa veya 5 sütundaki veriler değişse ve bu 5 sütunun tümü de dizine eklenmişse, "silme ve ekleme" işleminden daha iyi olabilirsiniz. Ancak, yalnızca 2 sütun değişiyorsa ve bunların kümelenmemiş dizinlerin bir parçası olmadığını söyleyebiliyorsa, kayıtları "Güncelleme" durumundan daha iyi olabilirsiniz, çünkü bu durumda yalnızca kümelenmiş dizin güncellenir (ve dizinlerde güncellenecek).


Daha fazla araştırmada, yukarıdaki yorumun, SQL Server'ın dahili olarak bir UPDATE işlemi yapmak için 2 ayrı mekanizmasına sahip olması nedeniyle gereksiz olduğunu buldum. - Bir "yerinde güncelleme" (yani, bir sütun değerini orijinal satırdaki yeniye değiştirerek) veya "yerinde olmayan bir GÜNCELLEME" olarak (DELETE ardından bir INSERT).

Yerinde güncellemeler kural ve mümkünse yapılır. Burada satırlar, tam olarak aynı sayfada aynı yerde, aynı oranda kalırlar. Sadece etkilenen baytlar şifrelenir. Tlog'da yalnızca bir kayıt var (güncelleme tetikleyicisi olmaması koşuluyla). Bir yığın güncelleniyorsa güncellemeler yapılır (ve sayfada yeterince yer vardır). Kümelenme anahtarı değişirse ancak satırın hiç hareket etmesi gerekmiyorsa güncellemeler yapılır.

Örneğin: Soyadı üzerinde kümelenmiş bir dizininiz varsa ve adlarınız varsa: Able, Baker, Charlie Artık Baker'ı Becker'e güncellemek istiyorsunuz. Hiçbir satır taşınmak zorunda değil. Böylece bu yerinde olabilir. Oysa eğer Able'ı Kumar'a güncellemeniz gerekiyorsa, satırların kaydırılması gerekecek (aynı sayfada olsalar bile). Bu durumda, SQL Server bir INSERT ve ardından bir SİLME yapar.

Yukarıdakileri göz önünde bulundurarak, normal bir UPDATE yapmanızı ve SQL Server'ın bunu dahili olarak nasıl yapmanın en iyi yolunu bulabilmenizi öneririm.

. - Herhangi bir SQL Server ile ilgili iç yapıları "GÜNCELLEME" iç donanım üzerinde ya da bu konuda daha ayrıntılı bilgi için Kalen Delaney, Paul Randal en vd kitabını kontrol SQL Server 2008 İçyapısı .


8

MERGE komutunu SQL 2008'de araştırdınız mı ? İşte temel bir örnek:

  merge YourBigTable ybt
  using (select distinct (RecordID) from YourOtherTable) yot
     on yot.Recordid = YBT.RecordID
  when NOT matched by target
  then  insert (RecordID)
        values (yot.DeviceID) ;

Bu temelde bir "UPSERT" komutudur. Varsa güncelleyin, yoksa ekleyin. ÇOK hızlı, çok havalı bir komut.


1
Bir GÜNCELLEME, kaputun altında aynı mekanikten daha hızlı değildir.
Mark Storey-Smith

Güncellemekten daha hızlıdır, daha önce mevcut olmayanları eklemek.
datagod

2
Durumun bu olduğunu biliyorsanız, kanıtlayın :)
Mark Storey-Smith

4

Ancak kendimi 30 milyon (3crore) kayıt olan bir masada Sil ve Ekle ve Güncelleştir'i kontrol ettim. Bu tabloda bir kümelenmiş benzersiz bileşik anahtar ve 3 Ayrıştırılmamış anahtar vardır. Sil ve Ekle için 9 dakika sürdü. Güncelleme için 55 dakika sürdü. Her satırda güncellendi sadece bir sütun var.

Bu yüzden sizden tahmin etmemenizi rica ediyorum. Denklemler, birçok sütun içeren ve çok sayıda veri içeren büyük tablolarla çalışırken değişecektir.


Bu davaya da değindim ancak daha sonra bazen kaynağa veya hedefe işaretler (temp veya perm) ekleyerek hedefin ipuçlarını veya alt-hedefini (tam birleştirme için geçerli değildir) ekleyerek optimize etmenin mümkün olduğunu keşfettim.
crokusek

3

Güncelleme kadar hızlı değil. İşin püf noktası hızlı bir ekleme yapmaktır, veriler eklenirken dizinleri devre dışı bırakmaktır.

Bunu kullanmayı düşünün:

-- disable indexes
ALTER INDEX [index_name] ON dbo.import_table DISABLE
-- ... disable more indexes

-- don't use delete if you don't care about minimal logging. truncate is faster
TRUNCATE TABLE dbo.import_table

-- just insert the new rows
INSERT dbo.import_table
SELECT
    *
FROM
    dbo.source_table

-- rebuild indexes
ALTER INDEX [index_name] ON dbo.import_table REBUILD
-- ... rebuild more indexes

Daha da hızlı olanı, db seçeneklerinde otomatik istatistik güncellemesini kapatmaktır. Tablo önemli ölçüde değiştirilirse çalıştırmalısınız

UPDATE STATISTICS dbo.import_table

veya

EXEC sp_updatestats

İstatistikleri güncel tutmak için düzenli olarak bir meslek olarak (günlük, db büyüklüğüne bağlı olarak haftalık). Dikkat edilmesi gereken şey, tablo boşken istatistikleri güncellemektir. Tablo tekrar doldurulduktan sonra çalıştırmazsanız bu, istatistikleri mahveder.


4
Bunun her zaman böyle olduğuna katılıyorum. Ayrıca, @ adopilot'un sorusundaki soru, 89m kayıtları içerdiğinden ve sadece 36k güncellemek istediğinden TRUNCATE ile silinemiyor.
Mark Storey-Smith,

Gönderiyi daha dikkatli okumayı öğrenmelisin! gönderiyi güncelleyeceğim ... aslında, çok fazla değişiklik yapmam gerekiyor.
Asken
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.