Tüm satırları güncelle


12

Her satırı tek bir sütun için son derece büyük bir Oracle tablosunda güncellemenin en verimli yolunu bilmek istiyorum. Örneğin:

update mytable set mycolumn=null;

veya:

update mytable set mycolumn=42;

Bilgilerim bayat olabilir. Yaptığım şey sütunu bırakmak için tabloyu değiştirmek. Ardından, kullanmak istediğim yeni değerin varsayılan değeri olan sütunu eklemek için tabloyu değiştirdim. Ardından, sütunun varsayılan değerini kaldırmak için tabloyu değiştirdim. Bunu sadece bir güncelleme yapmaktan çok daha hızlı buluyorum, ama daha iyi bir yöntem olduğunu hissediyorum.


Anladığım kadarıyla, varsayılan ile yeni bir boş olmayan sütun ekleme, Oracle'da yalnızca bir meta veri değişikliği. "Tüm satırları aynı değere güncelle" durumunu optimize edeceklerinden şüpheliyim. Bu sizin için ortak bir ameliyat mı?
Martin Smith

1
Her iki yöntemi de deneyin ve zamanlayın. Bunu yapmanı engelleyen nedir? Farklı bir sonuçla değil, aynı sonuçla bitmeniz gerektiğine bakın! Aksi takdirde karşılaştırma geçersizdir.
tvCa

@tvCa İki yolu da denedim. Sadece bir güncelleme yaparsam, yaklaşık iki saat sürer ve sonra öldürürüm. Bir sütunu düşürürsem, yalnızca birkaç saniye sürer. Varsayılan değeri olmayan bir sütun eklemek (sütunu geçersiz kılan) yalnızca birkaç saniye sürer. Varsayılan değeri olan bir sütun eklemek yaklaşık 30 dakika sürer. Örneğin, bir sütundaki tüm değerleri 'Bazı Değerler' olarak ayarlamak istersem, şu anda sütunu bırakıp ekliyorum. Bunu yapmanın daha hızlı bir yolu olup olmadığını bilmek istiyorum.
kainaw

2
11gR2 mi kullanıyorsunuz? @MartinSmith doğru. Yeni sütunu DEFAULT ile NOT NULL olarak eklemenin tablodaki tüm satırların güncellenmesini zorlayacak şekilde NULL olarak eklemekten çok daha hızlı bir değişiklik olduğunu görmek için buraya bakın (tıpkı bir UPDATE ifadesinin yayınlanması gibi). Gördüğüm sorun daha sonra VARSAYILAN değerini kaldırmaktır, çünkü performans artışı VARSAYILAN'ı sözlükte depolamaktan kaynaklanır. Ayrıca bu noktada NOT NULL kısıtlamasıyla uğraşmak zorunda kalacaksınız.
ansible

Yanıtlar:


2

Bu toplu güncellemeyi yaparken, bu tabloya karşı olan diğer etkinliklere çok şey bağlıdır. Umarım yapmak istediklerinizin bazı örneklerini çalıştırabilir ve hangisinin en iyi olduğuna dair bir fikir edinebilirsiniz. Ben denemek istiyorum:

  1. Tekli çalıştırın update table set column_name = blah;
  2. Tablodaki tüm birincil anahtarları seçmek için bir plSql döngüsü oluşturun ve bunlar arasında döngü yapın updating the column=blahve her X güncellemesini gerçekleştirin (belki 10000). Bu kodu kopyalayarak ve Birincil anahtarların ayrı bir bölümünü yapmasını sağlayarak paralel hale getirebilirsiniz.

OLTP sisteminde çok aktif olarak kullanılan bir tabloyla çok benzer bir sorun yaşadık ve onu 5x paralelleştirebildik ve her 10000'de bir 100+ MM satır tablosunda kullanıcı kilitleme etkisi olmadan koştuk. Masanız ne kadar büyükse veya ne tür bir uygulama çalıştırıyorsunuz ancak bu tür bir çözüm size uyabilir.


0

Hızlı bir şekilde UPDATE, tetikleyen tetikleyicileriniz olmadığından emin olun.

SELECT trigger_name, status FROM user_triggers WHERE table_name = 'MYTABLE';

ALTER TABLE mytable DISABLE ALL TRIGGERS;

Yalnızca işiniz bittiğinde istediklerinizi yeniden etkinleştirdiğinizden emin olun.

ALTER TRIGGER mytrigger ENABLE;

Ayrıca, dizin bakımının ek yükü ile karşılaşıyor olabilirsiniz. Dizinlerinizi ayrı olarak yeniden oluşturmayı deneyin. Bunu yapmak için, pappes tarafından verilen cevap yararlı olacaktır: /programming/129046/disable-and-later-enable-all-table-indexes-in-oracle

Ben burada referans için pappes cevap tekrar ediyorum. (Bu SPOOL komutunun platformunuz ve ortamınız hakkında varsayımlarda bulunduğunu unutmayın.)

set pagesize 0    
alter session set skip_unusable_indexes = true;
spool c:\temp\disable_indexes.sql
select 'alter index ' || u.index_name || ' unusable;' from user_indexes u;
spool off
@c:\temp\disable_indexes.sql

İçe aktar ...

select 'alter index ' || u.index_name || ' rebuild online;'
  from user_indexes u;

-1

dizini kaldırın. sütunu güncelleyin. dizini geri döndür. ancak sütun tüm satırlar için bir ve aynı değeri içeriyorsa dizini bırakabilirsiniz.


-2

Alan sınırlamanız yoksa, yeni sütununuz o tabloya eklenmiş olarak tablonuzla aynı şekilde yeni bir tablo oluşturabilir ve eski tabloyu silebilirsiniz:

create new_table as
select old_table.*, (with or without default_Value) as new_column
from old_table;

1
Bu daha verimli olacak mı? Neden? Mevcut tabloya referans veren FK'ler varsa ne olur?
ypercubeᵀᴹ

evet, diğer örnek tabloda deneyebilir ve sonucu kendiniz görebilirsiniz. FK'ler varsa, tam olarak bilmiyorum, ancak verimli ise bunları devre dışı bırakıp etkinleştirebilirsiniz.
E_Salamon

-3

Birden çok güncelleme / işleme dizisi deneyin. Taahhüt olmadan çok fazla satırın Eklenmesi / Güncellenmesi / Silinmesi, ağır G / Ç yüküne yol açar. Blok boyutlarını ve kayıt boyutlarını ve malzemelerini bilerek oldukça optimize edilebilir.

Bir tablodaki tüm verileri silmek truncate table xiçin daha iyidir delete from x. Ayrıca tasfiye işlemi başka bir işlemin iş yükünü de arttırır.

Düzenleme:inmemory Sütun biçiminde bellekte tablo yükleme seçeneğini kullanın ve sonra güncelleştirme yapabilirsiniz. gerçekten DB'nizin ilişkilerine ve yapısına bağlıdır. Bu makaleye bakın .


3
Tablonun bir sütununu güncellemek istiyorlar. Nasıl yardımcı olabileceğini truncateveya nasıl deleteyardımcı olacağını görmüyorum .
ypercubeᵀᴹ

@ ypercube Az önce kesinti olmadan çoklu veri manipülasyonunun istenmeyen IO yüküne nasıl yol açtığını açıkladım; güncelleme veya diğer OLTP'ler olabilir.
Kurnaz

3
İşlemlerin sık sık G / Ç'yi nasıl azalttığını açıklayabilir misiniz ? Onlar olmaz artırmak için kontrol noktalarının I / O'yu?
mustaccio

3
Geleneksel olmayan terminoloji ("tx günlüğü", "oturumunuzu temizler") kullanımınız biraz kafa karıştırıcıdır. Birden fazla kısa işlem veya büyük bir işlem kullansanız da, oluşturulan yineleme kayıtlarının toplam hacmi aynı olacaktır. G / Ç işlemleri yalnızca yineleme günlüğü arabelleği diske yazıldığında (şimdilik tampon önbellek kontrol noktalarını bırakarak) gerçekleşir; Daha sonra, sık sık taahhütte bulunursanız ek G / Ç'ye neden oluyorsunuz, bu yüzden bunun G / Ç'yi nasıl azaltabileceğini merak ediyorum.
mustaccio

4
Tom Kyte'nin " sık yapılan taahhütler" hakkında söylediklerini okumak isteyebilirsiniz: asktom.oracle.com/pls/apex/… " yanlış, yanlış, yanlış. Çok yanlış .... Çok çok yanlış "
a_horse_with_no_name
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.