OracleBulkCopy özellikle ne yapar ve performansını nasıl optimize edebilirim?


14

Özellikleri özetlemek gerekirse: Bir satıcı (Oracle) veritabanına yaklaşık 5 milyon satır eklememiz gerekir. OracleBulkCopy(ODP.NET) kullanarak 500 bin satırlık gruplar için her şey harika gidiyor , ancak 5M'ye kadar ölçeklendirmeye çalıştığımızda, 1M işaretine ulaştığında performans yavaşlamaya başlar, daha fazla satır yüklendiğinde ve yavaş yavaş yavaşlar 3 saat sonra zaman aşımına uğrar.

Bunun tablodaki birincil anahtarla ilgili olduğundan şüpheleniyorum, ancak bilgi için Oracle forumlarını ve Stack Overflow'u trol ediyordum ve okuduğum şeylerin birçoğu (ayrıca, birçok yazı birbiriyle çelişiyor gibi görünüyor) ) . Birisinin süreci doğrudan ilgili bazı sorularla ilgili olarak rekor kıracağını umuyorum:

  1. Does OracleBulkCopysınıf konvansiyonel veya doğrudan yol yükleme kullanılır? Bunu şu şekilde onaylamamın bir yolu var mı?

  2. Varsayarsak o yapar kullanımı doğrudan yol yükleme: Oracle otomatik yük ve koyar geri çevrimiçi sonra onları sırasında kullanılamaz tüm endeksler ayarlar doğru mu? Bu etki için çeşitli ifadeler okudum ama yine, bunu teyit edemez.

  3. # 2 doğruysa, toplu kopyalama işlemini başlatmadan önce tabloda hangi dizinlerin olduğunu farketmeli mi? Öyleyse neden?

  4. # 3 ile ilgili olarak, genel olarak, kullanılmayan bir indeks ile toplu yükleme ile indeksin yükten önce bırakılması ve daha sonra yeniden oluşturulması arasında herhangi bir pratik fark var mı?

  5. 2. Eğer değil , doğru ya Anlamıyorum bazı uyarılar varsa, o zaman herhangi bir faydası olur ki açıkça dökme yük önce endeksi kullanılamaz hale ve sonra açıkça sonra onu yeniden?

  6. Daha fazla kayıt eklendikçe toplu kopyalama işleminin giderek daha yavaş büyümesine neden olabilecek başka dizin var mı? (Toplu işlemlerin günlüğe kaydedilmemesini beklememe rağmen, günlük kaydıyla ilgili bir şey olabilir mi?)

  7. Gerçekten varsa hiçbir İlk PK / dizin bırakarak kenara enfiye performans kalkmak başka bir yol, hangi adımları ben endeksi tamamen yok olmaz emin olmak için alabilir, yani veritabanına bağlantı içinde kaybolması durumunda sürecin ortasında?


Yan not: Kopyalanan veriler zaten tablodaki tek dizin olan PK'ye göre sıralanmış bir sıradadır.
Aaronaught

Verileri kaynaktan okumak için bir DataReader kullanıyor musunuz?
bernd_k

@bernd_k: Hayır, tamamen bellekten yükleniyor. Kesinlikle sorunun kaynağı bu değil.
Aaronaught

Yanıtlar:


14

Birkaç gün daha okuma ve deneme ve bunların çoğuna (çoğunlukla) cevap verebildim:

  1. Bunun gömülü bulundu ODP.NET belgelerinde (ironik değil de OracleBulkCopydocs):

    ODP.NET Toplu Kopyalama özelliği, Oracle SQL * Loader'a benzeyen ancak aynı olmayan doğrudan bir yol yükleme yaklaşımı kullanır. Doğrudan yol yükünü kullanmak geleneksel yüklemeden daha hızlıdır (geleneksel SQL INSERTdeyimlerini kullanarak ).

    Yani öyle görünüyor ki gelmez direkt yolu kullanın.

  2. Bu büyük bir toplu kopyalama işlemi yaparak ve SQL Developer dizin özellikleri alarak doğrulamak mümkün. Dizin , toplu kopya devam ederken olduğu gibi görünüyordu UNUSABLE. Bununla birlikte , OracleBulkCopy.WriteToServerindeks bir durumda başlarsa çalışmayı reddedeceğini de keşfettim UNUSABLE, bu yüzden burada daha fazla şey oluyor, çünkü dizini devre dışı bırakmak ve yeniden oluşturmak kadar basit olsaydı, başlangıç ​​durumunu önemsememeliydi.

  3. Bu bir fark yaratıyor , özellikle eğer endeks de bir sınırlamadır . Bu küçük gem yukarıda bağlantılı belgelerde bulundu:

    Etkin Kısıtlamalar
    Bir Oracle toplu kopyası sırasında, aşağıdaki kısıtlamalar varsayılan olarak otomatik olarak etkinleştirilir:

    • NOT NULL
    • UNIQUE
    • PRIMARY KEY (boş olmayan sütunlarda benzersiz kısıtlamalar)

    NOT NULLkısıtlamalar sütun dizisi oluşturma zamanında kontrol edilir. İhlal eden herhangi bir satırNOT NULLKısıtlamayı reddedilir.

    UNIQUEyükün sonunda dizinler yeniden oluşturulduğunda kısıtlamalar doğrulanır. Dizin, bir UNIQUEkısıtlamayı ihlal ederse Dizin Kullanılamaz durumunda bırakılır .

    Dokümantasyon , özellikle birincil anahtarlarda, yük sırasında neler olduğu konusunda biraz puslu , ancak bir şey kesinlikle kesindir - birincil anahtar ile bir anahtar olmadan farklı davranır . Yana OracleBulkCopymutlu Dizin kısıtlamaları ihlal izin (ve içine endeksi punt edecek UNUSABLEbitti devlet), benim önsezi oluyor da en o bina toplu kopya sırasında PK dizinini , ancak daha sonraya kadar doğrulamamasıdır .

  4. Gözlenen farkın Oracle'ın içinde mi yoksa sadece bir tuhaflığı mı olduğundan emin değilim OracleBulkCopy . Jüri hala bu konuda.

  5. OracleBulkCopy başlangıçta bir dizin varsa, bir istisna atar UNUSABLE durumdaysa , bu yüzden gerçekten tartışma konusu olur.

  6. Eğer varsa şunlardır diğer faktörler ben öğrenilmeli olarak, indeksleri (ve özellikle PK endeksleri), yine en önemlileri şunlardır:

  7. Aynı şemaya sahip global bir geçici tablo oluşturma (kullanma CREATE AS), ardından geçici tabloya toplu kopyalama ve son olarak düz bir eski oluşturmaINSERT olarak geçici tablodan gerçek tabloya . Geçici tablonun dizini olmadığından, toplu kopya çok hızlı olur ve sonINSERT ve veriler zaten bir tabloda olduğu de hızlıdır (5M satır tablodan tabloya kopyadan beri ekleme ipucunu henüz denemedim zaten 1 dakikadan az sürer).

    (Ab) 'nin geçici tablo alanını bu şekilde kullanmasının potansiyel sonuçlarından henüz emin değilim, ancak şu ana kadar bana herhangi bir sorun vermedi ve her iki satırın da bozulmasını önleme alternatifinden çok daha güvenli veya dizinler.

    Bunun başarısı, PK indeksinin problem olduğunu açıkça göstermektedir, çünkü geçici tablo ile kalıcı tablo arasındaki tek pratik fark budur - her ikisi de performans testleri sırasında sıfır satırla başlar.

Sonuç: ODP.NET kullanarak 100.000'den fazla satırı toplu olarak dizinlenmiş bir Oracle tablosuna toplu olarak kopyalamaya çalışmayın. Dizini bırakın (gerçekten ihtiyacınız yoksa) veya verileri farklı (dizine eklenmemiş) bir tabloya "önceden yükleyin" .


Birincil anahtar kısıtlamalarını kontrol etme konusunda emin değilim. Aynı verileri 2 kez Oracle tablosuna toplu olarak ekledim ve Select * 2 yinelenen satırı gösterir. Bu durumda Delete mümkün değildir, ancak kesme tablosu temiz duruma dönmeye yardımcı olur.
bernd_k

@bernd_k: Deletedizin olmadığından mümkün değil UNUSABLE. Bu, toplu kopyanın sonunda gerçekleşen kısıtlama denetiminin bir sonucudur.
Aaronaught

Bir SQL Server veri okuyucusundan bir Oracle veritabanına bulkcopy çağıran bir PowerShell skriptim var, birincil Anahtarlarla tüm hedef tablolar ve 205278 satıra kadar tablolarla ilgili sorunum yok. Ancak, ayrıntı tablolarını doldurmadan önce ana tabloları doldurmaya çok dikkat ediyorum. Tablodaki diğer dizinlerden herhangi birini kaldırmadım ve tablolar başlangıçta boş olduğunda sorunum yok.
bernd_k

@bernd_k: Evet, bu ciltte de çok fazla sorunum olmadı (son paragrafıma bakın). Milyonlara ulaştığınızda korkunçlaşıyor. Ayrıca, her toplu kopyadan sonra tabloyu bir süre boşaltırsanız bir fark olabilir (bu boşaltılmaz, eklenir ve dizinlerin büyüdükçe nasıl yavaşladığını bilirsiniz).
Aaronaught

Belki bir yaptığınızda yardımcı oluralter session set skip_unusable_indexes = true;
Wernfried Domscheit

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.