web-dev-qa-db-ja.com

drupalのnode_save()関数を高速化するにはどうすればよいですか?

Node_save()の非効率性に多くの問題を抱えています。しかし、ノードは私の問題を保存していますか?それが最終的に私が調べようとしていることです。

100,000回の繰り返しでループを作成しました。ノードオブジェクトが有効で正しく保存されるように、最低限必要なものを作成しました。ノードの保存コードは次のとおりです。

$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);
}

結果は次のとおりです。

100,000のノードが保存され、それぞれがnode_save()を使用しました。完了するまで5196.22秒かかりました。それは19秒だけを節約します。

控えめに言っても、特に この人は毎秒1200の個別の挿入クエリを取得している であり、 この人は毎秒25,000の挿入を取得している の場合、それは受け入れられません。

それで、ここで何が起こっているのですか?ボトルネックはどこですか?それはnode_save()関数であり、どのように設計されていますか?

それは私のハードウェアでしょうか?私のハードウェアは開発サーバーで、私以外は誰もいません-Intelデュアルコア、3 GHz、16 GBのRAMを搭載したUbuntu 12.04。

ループが実行されている間、私のリソース使用量は次のとおりです。MySQL27%CPU、6M RAM。 PHP 22%CPU 2M RAM。

私のmysql設定は perconaウィザード によって行われました。

Mysqlによると、CPU使用率が70%未満の場合 私の問題はディスクバインドです です。確かに、私は工場のWD Caviar 7200 RPMしか実行していませんが、1秒あたり19以上のインサートを取得する必要があります。

それほど前に私は 1日に30,000ノードを節約する について書きました。ただし、明確にするために、このノードは外力とは何の関係もありません。これは、node_save()の呼び出し速度を向上させる方法を学ぶための純粋なベンチマークです。

現実的には、node_saveを使用して毎分30,000項目をデータベースに取り込む必要があります。ノードの保存がオプションでない場合、私は自分のdrupal api関数 "node_batch_save()"またはmysqlの機能を利用して一括挿入を実行する機能を利用して何かを書くことができるかどうか疑問に思います- INSERT query 。これにどのように取り組むかについての考え?

9
blue928

Node_saveを使用すると、1分間に30 000挿入されることはありません。ありえない。

INSERTはそれだけなので高速です。 Node saveは複数の挿入(メインテーブル、リビジョンテーブル、各フィールドのテーブル)を実行し、エンティティキャッシュをクリアし、フックを起動します。フックは扱いにくい部分です。多くのcontribモジュールがある場合特に、作成者が「大量のノードを一度に保存する」ユースケースを考慮していない場合は、パフォーマンスを大幅に低下させる可能性があります(たとえば、動作が正しくない場合でも)。たとえば、これをMigrateクラスに追加する必要がありました。

  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);
  }

一方、フックを呼び出さないカスタム保存関数を作成すると、システムが予期しない状態で、一貫性のないデータを取得する危険があります。私はそんなことは決して勧めません。 xhprofを起動して、何が起こっているかを確認します。

10
Bojan Zivanovic

まず、XCache/APCをインストールし(PHP <5.5の場合)、Drupal用にmemcachedを構成します。

次に、次の場所にあるmysqltunerスクリプトを使用して、重いクエリ用にMySQL構成を最適化できます。 http://mysqltuner.pl

例えば。

# 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

その他の提案:

  • 不要なモジュールを無効にします(例 Devel 、コアデータベースロギングモジュールなど)。
  • PHPを最新またはそれ以上のブランチにアップグレードし、
  • PHP 64ビット以上のアーキテクチャでは、CPUに応じて再コンパイルします。
  • dbファイルまたはLAMP環境全体(たとえばSSDまたは メモリベースのファイルシステム )には、より高速なストレージデバイスを使用します。
  • PHPデバッガーまたはプロファイラーを使用して、パフォーマンスのボトルネックを見つけます(例 XDebug ProfilerDTrace または NuSphere PhpED PHPプロファイラ )、
  • gprof プロファイリングツールで時間のかかるdrushコマンドを実行して、パフォーマンスのボトルネックも見つけることができます
5
kenorb

Mongodbモジュールを使用してフィールドを保存します https://drupal.org/project/mongodb ここでの結果: http://cyrve.com/mongodb のとおり

1
giorgio79