Yanıtlar:
https://dev.mysql.com/doc/refman/8.0/en/insert-optimization.html
Bir satır eklemek için gereken süre, sayıların yaklaşık oranları gösterdiği aşağıdaki faktörlerle belirlenir:
- Bağlanıyor: (3)
- Sorguyu sunucuya gönderme: (2)
- Sorgu ayrıştırma: (2)
- Satır ekleme: (1 × satır boyutu)
- Dizin ekleme: (1 × dizin sayısı)
- Kapanış: (1)
Bundan, açık bir şekilde, büyük bir ifade göndermenin, ekleme ifadesi başına 7 ek yükü kurtaracağı açıktır;
Aynı istemciden aynı anda birden çok satır ekliyorsanız, aynı anda birden çok satır eklemek için birden çok VALUES listeli INSERT ifadeleri kullanın. Bu, tek satırlık ayrı INSERT ifadeleri kullanmaktan çok daha hızlıdır (bazı durumlarda birçok kez daha hızlıdır).
Ben o istendi neredeyse iki buçuk yıl sonra bu soruya cevap biliyorum, ama sadece şu anda gerçekten de ekin başına birden fazla DEĞER blokları yapıyor gösterileri olduğunu ben üzerinde çalıştığım bir projeden bazı zor verileri sağlamak istedik KADAR sıralı tek VALUE bloğundan daha hızlı INSERT ifadeleri.
C # 'da bu kıyaslama için yazdığım kod, bir MSSQL veri kaynağından (~ 19.000 satır, tümü herhangi bir yazma başlamadan önce okunur) belleğe veri okumak için ODBC kullanır ve MySql .NET bağlayıcı (Mysql.Data. *) Şeyler Verileri bellekten MySQL sunucusundaki bir tabloya hazırlanmış ifadeler aracılığıyla yerleştirin. Hazırlanan INSERT başına VALUE blok sayısını dinamik olarak ayarlamama izin verecek şekilde yazılmıştır (yani, bir çalıştırmadan önce n değerini ayarlayabileceğim bir seferde n satır ekle.) Ayrıca testi de çalıştırdım. her biri için birden çok kez
Tekli VALUE bloğu yapmak (örneğin, bir seferde 1 satır) çalıştırmak 5,7 - 5,9 saniye sürdü. Diğer değerler aşağıdaki gibidir:
Bir seferde 2 satır: 3,5 - 3,5 saniye
Bir seferde 5 satır: 2,2 - 2,2 saniye Her
seferinde 10 satır: 1,7 - 1,7 saniye Her
seferinde 50 satır: 1,17 - 1,18 saniye Her
seferinde 100 satır: 1,1 - 1,4 saniye
Bir seferde 500 satır: 1.1 - 1.2 saniye
Bir seferde 1000 satır: 1.17 - 1.17 saniye
Yani evet, sadece 2 veya 3 yazıyı bir araya getirmek bile, n = 5 ve n = 10 arasında bir yere ulaşana kadar, hızın çarpıcı bir şekilde iyileşmesini sağlar (n, bir faktör tarafından kesilir), ve n = 10 ila n = 50 aralığında bir yerde gelişme göz ardı edilebilir hale gelir.
İnsanların (a) çok hazırlılık fikrinin kullanılıp kullanılmayacağına ve (b) ifade başına kaç tane VALUE bloğu oluşturulacağına karar vermesine yardımcı olacağını umuyoruz (sorguyu maksimum sorgu boyutunu geçecek kadar büyük verilerle çalışmak istediğinizi varsayarsak) sunucuda max_allowed_packet değerine bağlı olarak muhtemelen daha büyük veya daha küçük birçok yerde varsayılan olarak 16MB olduğuna inanıyorum MySQL için.)
İşlemci bir motor kullanıp kullanmadığınız ve otomatik devreye girip girmediğiniz önemli bir faktördür.
Otomatik taahhüt varsayılan olarak açıktır ve muhtemelen açık bırakmak istersiniz; bu nedenle, yaptığınız her ekleme kendi işlemini yapar. Bu, her satır için bir ekleme yaparsanız, her satır için bir işlem yapacağınız anlamına gelir.
Tek bir iş parçacığı varsayıldığında, sunucunun HER SATIR için diske bazı verileri senkronize etmesi gerektiği anlamına gelir. Verilerin kalıcı bir depolama konumuna ulaşmasını beklemesi gerekir (umarım RAID denetleyicinizdeki pil destekli koç). Bu doğal olarak oldukça yavaştır ve muhtemelen bu durumlarda sınırlayıcı faktör olacaktır.
Tabii ki işlemsel bir motor (genellikle innodb) kullandığınızı ve dayanıklılığı azaltmak için ayarları değiştirmediğinizi varsayıyorum.
Ayrıca bu ekleri yapmak için tek bir iş parçacığı kullandığınızı varsayıyorum. MySQL'in bazı sürümlerinin innodb'de çalışma grubu taahhüdü bulunduğundan, birden çok iş parçacığı çamurunu biraz karıştırır - bu, kendi taahhütlerini yapan birden çok iş parçacığının işlem günlüğüne tek bir yazma paylaşabileceği anlamına gelir, çünkü bu, kalıcı depolama için daha az eşitleme anlamına gelir .
Öte yandan, çok satırlı uçları GERÇEKTEN KULLANMAK İSTEDİĞİNİZ.
Karşı üretken hale gelme sınırı vardır, ancak çoğu durumda en az 10.000 satırdır. Dolayısıyla, bunları 1000 satıra kadar topluyorsanız, muhtemelen güvendesiniz.
MyISAM kullanıyorsanız, başka bir şey daha var, ama sizi bunlarla sıkmayacağım. Barış.
Genel olarak veritabanına yapılan çağrı sayısı ne kadar az olursa o kadar iyidir (yani daha hızlı, daha verimli), bu nedenle ekleri veritabanı erişimini en aza indirecek şekilde kodlamaya çalışın. Bir bağlantı havuzu kullanmadığınız sürece, her veritabanı erişiminin bir bağlantı oluşturması, sql yürütmesi ve ardından bağlantıyı yırtılması gerekir. Biraz havai!
Şunları yapmak isteyebilirsiniz:
Sunucu terazi (onun kesin olan ok ne kadar iyi bağlı olarak PostgreSQl
, Oracle
ve MSSQL
), çoklu iş parçacığı ve çoklu bağlantı ile yukarıdaki şeyi yap.
Genel olarak, bağlantı ek yükü nedeniyle birden fazla kesici uç daha yavaş olacaktır. Bir kerede birden fazla kesici uç kullanılması, kesici uç başına ek masrafı azaltır.
Hangi dili kullandığınıza bağlı olarak, muhtemelen db'ye gitmeden önce programlama / komut dosyası dilinizde bir toplu iş oluşturabilir ve her eki toplu işleme ekleyebilirsiniz. Daha sonra, bir bağlantı işlemini kullanarak büyük bir toplu iş yürütebilirsiniz. İşte Java'da bir örnek.
MYSQL 5.5 Bir sql insert deyimi ~ 300 ila ~ 450 ms sürdü. aşağıdaki istatistikler satır içi birden çok ekleme ifadesi içindir.
(25492 row(s) affected)
Execution Time : 00:00:03:343
Transfer Time : 00:00:00:000
Total Time : 00:00:03:343
Satır içi gitmek için bir yol olduğunu söyleyebilirim :)
Ekler söz konusu olduğunda Mysql ve MariaDB'nin ne kadar kötü optimize edildiği çok saçma. MySQL 5.7 ve mariadb 10.3'ü test ettim, bunlar üzerinde gerçek bir fark yok.
Bunu NVME diskleri, 70.000 IOPS, 1.1 GB / sn seq verimi olan bir sunucuda test ettim ve bu tam çift yönlü (okuma ve yazma).
Sunucu aynı zamanda yüksek performanslı bir sunucudur.
20 GB koç verdi.
Veritabanı tamamen boş.
Çok satırlı ekler alırken aldığım hız saniyede 5000 eklendi (1MB ila 10MB'lık veri parçalarıyla denedim)
Şimdi ipucu:
Başka bir iş parçacığı ekleyip aynı tablolara eklersem aniden 2x5000 / sn. Bir iplik daha ve toplam 15000 / sn var
Bunu düşünün: ONE iş parçacığı ekleri yaparken, diske sırayla yazabileceğiniz anlamına gelir (dizinler hariç). İş parçacıklarını kullanırken, olası performansı düşürürsünüz, çünkü artık çok daha rastgele erişim yapması gerekiyor. Ancak gerçeklik kontrolü, mysql'in o kadar kötü bir şekilde optimize edildiğini gösteriyor ki, iş parçacıkları çok yardımcı oluyor.
Böyle bir sunucu ile mümkün olan gerçek performans muhtemelen saniyede milyonlarca, CPU boşta, disk boşta.
Nedeni, mysql gibi içsel gecikmeler olduğu için oldukça açıktır.
id
, parent_id
) DEĞERLERİNE (1, NULL) GİRİN . Sonraki değer kümelerinden biri o satıra bağlanır. Parçalara ayrılırsanız ve bu set başka bir parçaya gelirse, ilk işlemden önce işlenebilir ve tüm işlem başarısız olur. Bununla nasıl başa çıkılacağı hakkında bir fikrin var mı?
birden fazla kesici uç daha hızlıdır, ancak gerekir. başka bir thrik devre dışı bırakıyor kontrolleri geçici yapmak uçlar çok daha hızlı yapmak. Masanızın olması ya da olmaması önemli değil. Örneğin, yabancı anahtarları devre dışı bırakmayı test edin ve hızın tadını çıkarın:
SET FOREIGN_KEY_CHECKS=0;
ekler tarafından ekledikten sonra tekrar açmalısınız:
SET FOREIGN_KEY_CHECKS=1;
bu, büyük veri eklemenin yaygın yoludur. veri bütünlüğü bozulabilir, böylece yabancı anahtar kontrollerini devre dışı bırakmadan önce bununla ilgilenmelisiniz.