Bir veritabanı bir işlemdeki dizinlerini hangi noktada günceller?


11

Hem bir dizin hem de bir işlem dahil ekler olaylar dizisini anlamaya çalışıyorum.

Örneğin, Oracle belgeleri şunları belirtir:

Veri yüklemeden önce bir veya daha fazla dizin oluşturduysanız (veya varsa), her satır eklendiğinde veritabanı her dizini güncellemelidir.

Ancak, bir işlem oluşturur, beş satır ekler ve sonra taahhüt verirsem ne olur? Dizinler her ekleme için mi yoksa yalnızca bitiş noktasında mı güncelleniyor?

Mantık bana yalnızca taahhüt noktasında güncelleneceklerini söylüyor, çünkü güncellenmiş bir dizin bu kayıtlar işlenene kadar kullanılamayabilir. Ama bu doğru mu?

Eğer öyleyse, eklemek için 1m satırlarım olduğunda, en iyi performans için, 100k kayıtlarının 10 işlemini değil, tüm satırların büyük bir taahhüdünü yapmalıyım? Tabii ki 999,999. Satır başarısız olursa, bunun daha büyük bir geri dönüş riski taşıdığını fark ediyorum.

Terminolojim biraz dışarsa özür dilerim. Ticaretle DBA değilim. Oracle ve Postgres en çok kullandığım olsa da, genel olarak veritabanları gibi belirli bir veritabanıyla ilgilenmiyorum. Bu konuyu araştırdım ancak kesin bir cevap bulamıyorum.

Yanıtlar:


8

SQL Server ve Oracle ile çalışıyorum. Muhtemelen bazı istisnalar vardır, ancak bu platformlar için genel cevap, veri ve indekslerin aynı anda güncelleneceği yönündedir.

İşlemin sahibi olan oturum ve diğer oturumlar için dizinlerin güncelleştirilmesi arasında bir ayrım çizmenin yararlı olacağını düşünüyorum. Varsayılan olarak, diğer oturumlar işlem tamamlanana kadar güncellenmiş dizinleri görmez. Ancak, işlemin sahibi olan oturumda derhal güncellenen dizinler görüntülenir.

Bunu düşünmenin bir yolu için, birincil anahtarlı bir masada düşünün. SQL Server ve Oracle'da bu bir dizin olarak uygulanır. Çoğu zaman INSERTbirincil anahtarı ihlal edecek bir an yapılırsa hemen bir hata olmasını istiyoruz . Bunun olabilmesi için indeksin verilerle aynı zamanda güncellenmesi gerekir. Postgres gibi diğer platformların, yalnızca işlem tamamlandığında denetlenen ertelenmiş kısıtlamalara izin verdiğini unutmayın.

İşte genel bir durumu gösteren hızlı bir Oracle demosu:

CREATE TABLE X_TABLE (PK INT NULL, PRIMARY KEY (PK));

INSERT INTO X_TABLE VALUES (1);
INSERT INTO X_TABLE VALUES (1); -- no commit

İkinci INSERTifade bir hata verir:

SQL Hatası: ORA-00001: benzersiz kısıtlama (XXXXXX.SYS_C00384850) ihlal edildi

00001. 00000 - "benzersiz kısıtlama (% s.% S) ihlal edildi"

* Neden: Bir UPDATE veya INSERT deyimi yinelenen bir anahtar eklemeye çalıştı. DBMS MAC modunda yapılandırılmış Güvenilen Oracle için, farklı bir düzeyde yinelenen bir giriş varsa bu mesajı görebilirsiniz.

* Eylem: Benzersiz kısıtlamayı kaldırın veya anahtarı takmayın.

Aşağıdaki dizin güncelleme eylemini görmek isterseniz SQL Server'da basit bir demo. İlk önce bir milyon satır ve VALsütun üzerinde kümelenmemiş bir dizin içeren iki sütun tablosu oluşturun :

DROP TABLE IF EXISTS X_TABLE_IX;

CREATE TABLE X_TABLE_IX (
ID INT NOT NULL,
VAL VARCHAR(10) NOT NULL
PRIMARY KEY (ID)
);

CREATE INDEX X_INDEX ON X_TABLE_IX (VAL);

-- insert one million rows with N from 1 to 1000000
INSERT INTO X_TABLE_IX
SELECT N, N FROM dbo.Getnums(1000000);

Aşağıdaki sorgu kümelenmemiş dizini kullanabilir, çünkü dizin bu sorgu için bir kaplama dizinidir. Yürütmek için gereken tüm verileri içerir. Beklendiği gibi, iade alınmaz.

SELECT *
FROM X_TABLE_IX
WHERE VAL = 'A';

sorgu 1

Şimdi bir işlem VALbaşlatalım ve tablodaki hemen hemen tüm satırlar için güncelleme yapalım :

BEGIN TRANSACTION

UPDATE X_TABLE_IX
SET VAL = 'A'
WHERE ID <> 1;

İşte bunun için sorgu planının bir parçası:

sorgu 2

Kırmızı ile çevrelenmiş, kümelenmemiş dizine yapılan güncellemedir. Mavi daire içine alınmış, esasen tablonun verileri olan kümelenmiş dizine yapılan güncellemedir. İşlem yapılmamasına rağmen, verilerin ve dizinin sorgunun yürütülmesinin bir bölümünde güncellendiğini görüyoruz. Muhtemelen diğer faktörlerle birlikte verilerin boyutuna bağlı olarak bunu her zaman bir planda görmeyeceğinizi unutmayın.

İşlem hala tamamlanmadıysa, SELECTsorguyu yukarıdan tekrar gözden geçirelim .

SELECT *
FROM X_TABLE_IX
WHERE VAL = 'A';

resim açıklamasını buraya girin

Sorgu iyileştirici yine de dizini kullanabiliyor ve bu sefer 999999 satırın döndürüleceğini tahmin ediyor. Sorguyu yürütmek beklenen sonucu döndürür.

Bu basit bir demodu ama umarım bazı şeyleri temizledi.

Bir kenara, bir endeksin hemen güncellenmediği iddia edilebilir birkaç durumun farkındayım. Bu, performans nedenleriyle yapılır ve son kullanıcı tutarsız verileri göremez. Örneğin, bazen siler SQL Server'daki bir dizine tam olarak uygulanmayacaktır. Bir arka plan işlemi çalışır ve sonunda verileri temizler. Merak ediyorsanız hayalet kayıtlarını okuyabilirsiniz .


Bu süper bir cevap - ve merak ettiğim başka bir şeye de cevap veriyor: Ekle'de veya Taahhütte birincil anahtar (veya benzeri) ihlali oluşup oluşmayacağı. Böyle eksiksiz bir yanıt için teşekkürler.
Mark Ireland

İlgili soru (bir kısıtlama ihlali ne zaman gerçekleşeceği hakkında) ertelenmiş işlemleri kullanıp kullanmadığınızla ilgilidir. Örneğin SQL Server, ertelenmiş işlem uygulamadığından, tüm ihlaller ifadelerin sonunda gerçekleşir. Diğer DBMS'ler vardır (örneğin Postgres, ancak tüm kısıtlama türleri için olmasa da), bu nedenle bir kısıtlama ertelendiğinde, işlemin tamamlanma aşamasında ihlal kontrol edilir).
ypercubeᵀᴹ

Oracle ayrıca ertelenmiş kısıtlamaları da destekliyor
BobC

1

Deneyimlerim, 1.000.000 satır eklemenin aslında bir toplu ekler kullandığınızdan daha fazla kaynak gerektirmesi ve tamamlanması daha uzun sürecektir. Bu, örnek olarak, 10.000 satırlık 100 kesici uç içine uygulanabilir.

Bu, yerleştirilen partilerin ek yükünü azaltır ve bir parti başarısız olursa daha küçük bir geri dönüş olur.

Her durumda, SQL Server için toplu ekler yapmak için kullanılabilecek bir bcp yardımcı programı veya BULK INSERT komutu vardır.

Ve elbette, bu yaklaşımı ele almak için kendi kodunuzu da uygulayabilirsiniz.


1
Genel olarak, bir dizine ihtiyaç duyan bir tabloya çok sayıda satır eklemeniz gerekiyorsa, dizini bırakmak, verileri yüklemek ve ardından dizini yeniden oluşturmak daha hızlı olacaktır. Oracle, / * + APPEND * / ipucunu kullanarak doğrudan yol toplu yükleme seçeneğini de destekler.
BobC
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.