Drupal'ın node_save () işlevini nasıl hızlandırabilirim?


9

Ben node_save () verimsizliği ile ilgili çok sorun yaşıyorum. Ama düğüm sorunumu kurtarıyor mu? Nihayetinde bulmaya çalıştığım şey bu.

100.000 yinelemeli bir döngü oluşturdum. Düğüm nesnesinin geçerli olması ve doğru şekilde kaydedilmesi için minimum değeri oluşturdum. Düğüm kaydetme kodu:

$node = new stdClass();
        $node->type = "test_page";

        node_object_prepare($node);

        $node->uid = 1;
        $node->title = $node_title;
        $node->status = 1;
        $node->language = LANGUAGE_NONE;
        if($node = node_submit($node)){
            node_save($node);
}

Sonuçlar burada:

Her biri node_save () kullanan 100.000 düğüm kaydedildi. Tamamlanması 5196,22 saniye sürdü. Bu SADECE 19 saniyede bir tasarruf sağlar.

En azını söylemek gerekirse, özellikle bu kişi saniyede yaklaşık 1200 ayrı ekleme sorgusu alırken ve bu kişi saniyede 25.000 ekleme alıyorsa , bu kabul edilemez .

Peki, burada neler oluyor? Darboğaz nerede? Node_save () işleviyle birlikte mi ve nasıl tasarlanmış?

Bu benim donanımım olabilir mi? Donanımım bir geliştirme sunucusudur, benim dışında kimse yok - Intel çift çekirdekli, 3Ghz, Ubuntu 12.04, 16 gm ram.

Döngü çalışırken kaynak kullanımım: MySQL% 27 CPU, 6M RAM; PHP% 22 CPU 2M RAM.

MySQL yapılandırmam percona sihirbazı tarafından yapıldı .

Mysql, CPU kullanımımın% 70'in altında olması sorunumun diske bağlı olduğunu söylüyor . Verilmiş, değirmen WD Caviar 7200 RPM sadece bir çalışma var, ama umarım onunla bir saniye 19'dan fazla ekler almalıyım!

Çok uzun zaman önce bir günde 30.000 düğümü kaydetmeyi yazdım . Ancak açık olmak gerekirse, bu düğümün herhangi bir dış güçle hiçbir ilgisi yoktur. Bu, node_save () işlevine yapılan çağrıların hızını nasıl artıracağınızı öğrenmek için bir ölçüttür.

Gerçekçi olarak, node_save kullanarak her dakika veritabanına 30.000 öğe almak gerekir. Düğüm kaydetme bir seçenek değilse, kendi drupal api işlevi "node_batch_save ()" veya mysql INSERT sorgusu ile toplu ekler yapmak yeteneğinden yararlanan bir şey yazabilir miyim merak ediyorum . Buna nasıl yaklaşılacağına dair düşünceler?


2
Ham kesici uç performansı ile node_save'in yapacağı şey arasında büyük bir fark vardır. Bir kere node_save bir dizi okuma ve yazma gerçekleştirir. Ancak, daha fazla veri olmadan olası darboğazları ve optimizasyonları tartışmanın bir anlamı yoktur.
Alfred Armstrong

Neden Drupal'ı amaçlarınız için bu şekilde kullandığınızı düşünmelisiniz. Düz bir tabloda çok fazla veri yakalamak ve Drupal kullanarak görüntülemek istiyorsanız, Drupal'ı yazarken tamamen atlamak ve Görünümler vb. Kullanarak verileri entegre etmek için özel bir modül kullanmak isteyebilirsiniz
Alfred Armstrong

Şişe boynunun veritabanı tarafında olduğundan şüpheliyim. Düğüm kaydetme arka planda çok şey yapar: her biri herhangi bir sayıda modül çağırabilecek bir dizi kanca (hook_node_presave, hook_entity_presave, hook_node_insert, hook_entity_insert, vb.) Çağıracaktır. Ayrıca node_save bu düğüm için izinleri yeniden oluşturacak ve bu düğüm için önbelleği temizleyecek ...
Alice Heaton

@AlfredArmstrong Başka bir veritabanındaki verilere dayalı düğümler oluşturuyorum. Verileri doğru drupal içerik türüne kalıplar ve node_save. Müşterilerim esas olarak drupal'a geçmek isteyen üniversitelerdir. On yıl sonra kendi web çözümünü kullandıklarında taşımak istedikleri 200.000 ile 1.000.000 arasında düğümün (departmanların site içeriği, öğrenci ve fakülte kayıtları vb.) Olması nadir değildir. Cesaret verici ama yine de arzu edilen yaklaşımdan daha az olan bunu okudum. evolvingweb.ca/story/…
blue928

.. bu yüzden olabildiğince drupal olarak kalmayı tercih ederim. Bu kadar veri ile düğüm kaydetmeyi kullanmak bütünlüğü sağlar. Eğer işe yaramazsam, yaratıcı olmaya hazırım.
blue928

Yanıtlar:


10

Node_save kullanarak asla 30.000 kesici ucu alamazsınız. Olmaz.

Bir INSERT hızlıdır çünkü tek yaptığı budur. Düğüm kaydetme çoklu ekler (ana tablo, revizyon tablosu, her alan için bir tablo) yapar, varlık önbelleklerini temizler ve kancaları ateşler. Kancalar zor kısmıdır. Performansı gerçekten öldürebilecek çok sayıda katkıda bulunan modülünüz (hatta hatalı çalışan bir modülünüz) varsa, özellikle yazar "Aynı anda tonlarca düğüm kaydediyorum" kullanım durumunu hesaba katmadıysa. Örneğin, bunu Migrate sınıfıma eklemek zorunda kaldım:

  public function processImport(array $options = array()) {
    parent::processImport($options = array());
    // Do not force menu rebuilding. Otherwise pathauto will try to rebuild
    // in each node_save() invocation.
    variable_set('menu_rebuild_needed', FALSE);
  }

Diğer taraftan, kanca gerektirmeyen özel bir kaydetme işlevi yazarsanız, sistem tarafından beklenmeyen bir durumda tutarsız veri alma tehlikesi vardır. Bunu yapmayı asla tavsiye etmem. Xhprof'u çalıştırın ve neler olduğunu görün.


Bazı geçiş modülleri, toplu tasarruf düğümlerini nasıl elde ediyorlar? Demek istediğim, her şeyin sonunda, hepsi bir INSERT ifadesine dayanıyor, değil mi? Taşıma sınıfınız, düğüm kaydetme özelliğini kullanmadığınızda, ancak yine de tablolar arasında veri bütünlüğünü korumaya ihtiyaç duyduğunuzda sonuçta 'kaynak'tan' hedefe 'nasıl eklenir?
blue928

Karşılaştığım tüm geçiş modülleri bir node_save kullanıyor.
Alfred Armstrong

1
@ blue928 O dediğini yapar kullanılmasını node_save(), fakat kaydetme her düğümün sonra menü önbelleği yeniden oluşturuluyor OtoYol gibi neden olabilir bilinen sorunları hafifletmek için bazı kod ekler
Clive

ah, tamam, anlıyorum. Bojan kodunuzu yol otomatik gibi darboğazlarla nasıl uğraştığınızı görebileceğim bir modülde veya çevrimiçi olarak kullanılabilir mi? Xhprof ile iyi fikir. Bunu kontrol edeceğim.
blue928

5

Her şeyden önce, XCache / APC'yi (PHP <5.5 için) yükleyin ve Drupal için memcached'ı yapılandırın.

Ardından, http://mysqltuner.pl adresinde bulunan mysqltuner komut dosyasını kullanarak MySQL yapılandırmanızı ağır sorgular için optimize edebilirsiniz.

Örneğin

# performance tweaks (adjusted based on mysqltuner.pl)
query_cache_size = 32M
query_cache_limit = 256M
join_buffer_size = 32M
key_buffer = 8M
max_allowed_packet = 32M
table_cache = 512
sort_buffer_size = 1M
net_buffer_length = 8K
read_buffer_size = 256K
read_rnd_buffer_size = 1M
myisam_sort_buffer_size = 8M

# When making adjustments, make tmp_table_size/max_heap_table_size equal
tmp_table_size = 16M
max_heap_table_size = 16M

thread_cache_size = 4

Diğer öneriler:

  • ihtiyacınız olmayan modülleri devre dışı bırakın (örn. Devel , çekirdek Veritabanı Günlüğü modülü, vb.),
  • PHP'nizi en son veya daha yüksek bir boyuta yükseltmek,
  • CPU'nuza bağlı olarak PHP'nizi 64 bit veya daha yüksek mimari için yeniden derleyin,
  • db dosyalarınız veya tüm LAMP ortamınız için (örneğin SSD veya bellek tabanlı dosya sistemi ) daha hızlı depolama aygıtını kullanın ,
  • herhangi bir performans darboğazını bulmak için PHP hata ayıklayıcı veya profiler kullanın (örn. XDebug Profiler , DTrace veya NuSphere PhpED PHP Profiler ),
  • altında bazı zaman alıcı drush komutunu çalıştırın gprof bazı performans darboğaz yanı bulabilmesi için, profil oluşturma aracı

1
MySQL'in ayarlanması büyük bir fark yaratıyor gibi görünüyor. Sadece mysqltuner.pl tarafından verilen ipuçlarını takip ederek yaklaşık 80 node_saves bir dakikadan 700'e gittim.
John McCollum

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.