drupal의 node_save () 함수 속도를 어떻게 높일 수 있습니까?


9

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

결과는 다음과 같습니다.

각각 node_save ()를 사용하여 100,000 개의 노드가 저장되었습니다. 완료하는 데 5196.22 초가 걸렸습니다. 19 초만 절약됩니다.

특히, 허용되지 않습니다 즉, 적어도 말을하려면 이 사람이 초당 1,200 개별 삽입 쿼리를 받고 , 그리고 이 사람이 초당 25,000 삽입을 받고있다 .

무슨 일이야? 병목 현상은 어디에 있습니까? node_save () 함수와 함께 설계되었으며 어떻게 설계 되었습니까?

내 하드웨어 일까? 저의 하드웨어는 저를 제외하고는 개발 서버입니다. Intel 듀얼 코어, 3Ghz, Ubuntu 12.04, 16 기가의 램.

루프가 실행되는 동안 내 리소스 사용량은 다음과 같습니다. MySQL 27 % CPU, 6M RAM; PHP 22 % CPU 2M RAM.

내 mysql 구성은 percona 마법사에 의해 수행되었습니다 .

Mysql에 따르면 내 CPU 사용량이 70 % 미만이면 내 문제는 디스크 바운드 입니다. 물론, 나는 WD Caviar 7200 RPM의 분쇄기만을 가지고 있지만, 나는 그것을 희망하는 초 당 19 개 이상의 인서트를 얻어야한다!

얼마 전에 나는 하루에 30,000 개의 노드를 절약하는 것에 대해 썼습니다 . 그러나 분명히이 노드는 외부 힘과는 아무런 관련이 없습니다. node_save () 호출 속도를 높이는 방법을 배우는 것은 전적으로 벤치 마크입니다.

실제로 node_save를 사용하여 1 분마다 데이터베이스에 30,000 개의 항목을 가져와야합니다. 노드 저장이 옵션이 아닌 경우 내 drupal api 함수 "node_batch_save ()"또는 INSERT 쿼리로 대량 삽입을 수행하는 mysql의 기능을 활용할 수있는 기능을 작성할 수 있는지 궁금 합니다 . 접근하는 방법에 대한 생각?


2
가공되지 않은 인서트 성능과 node_save의 기능에는 큰 차이가 있습니다. 우선 node_save는 일련의 읽기 및 쓰기를 수행합니다. 그러나 더 많은 데이터없이 가능한 병목 현상과 최적화에 대해 논의 할 필요는 없습니다.
Alfred Armstrong

왜 Drupal을 이러한 목적으로 사용하는지 고려해야합니다. 플랫 테이블에서 많은 양의 데이터를 캡처하고 Drupal을 사용하여 표시하려는 경우 Drupal을 작성할 때 Drupal을 우회하고 사용자 정의 모듈을 사용하여 Views 등을 사용하여 데이터를 통합 할 수 있습니다.
Alfred Armstrong

병목이 데이터베이스쪽에 있는지 의심됩니다. 노드 저장은 백그라운드에서 많은 작업을 수행합니다. 각 후크는 많은 수의 모듈을 호출 할 수있는 많은 후크 (hook_node_presave, hook_entity_presave, hook_node_insert, hook_entity_insert 등)를 호출합니다. 또한 node_save는 해당 노드에 대한 권한을 다시 작성하고 해당 노드에 대한 캐시를 지 웁니다.
Alice Heaton

@AlfredArmstrong 다른 데이터베이스에있는 데이터를 기반으로 노드를 만들고 있습니다. 올바른 drupal 컨텐츠 유형으로 데이터를 성형하고 node_save합니다. 내 고객은 주로 드루팔로 전환하려는 대학입니다. 웹 솔루션에서 10 년 동안 자신의 웹 솔루션을 사용한 후 마이그레이션하려는 20 만에서 1,000,000 개의 노드 (부서 사이트 내용, 학생 및 교직원 레코드 등)를 갖는 것은 드문 일이 아닙니다. 나는 이것을 장려하지만 여전히 바람직한 접근법보다 적습니다. evolvingweb.ca/story/…
blue928

.. 그래서 나는 가능한 한 drupally 유지하는 것을 선호합니다. 이 많은 데이터와 함께 노드 저장을 사용하면 무결성이 보장됩니다. 그것이 작동하지 않으면 창의력을 기꺼이 할 것입니다.
blue928

답변:


10

node_save를 사용하여 1 분에 30 000 개의 삽입물을 얻을 수 없습니다. 절대 안돼.

INSERT는 빠르기 때문에 빠릅니다. 노드 저장은 여러 삽입 (메인 테이블, 개정 테이블, 각 필드에 대한 테이블)을 수행하고 엔티티 캐시를 지우고 후크를 발생시킵니다. 고리는 까다로운 부분입니다. 성능을 떨어 뜨릴 수있는 많은 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를 시작하고 무슨 일이 일어나고 있는지 확인하십시오.


일부 마이그레이션 모듈은 어떻게 대량 저장 노드를 만들 수 있습니까? 결국 모든 것이 INSERT 문으로 요약됩니다. 노드 저장을 사용하지 않고 여전히 테이블에서 데이터 무결성을 유지해야 할 때 마이그레이션 클래스는 어떻게 '소스'에서 '대상'으로 삽입합니까?
blue928

내가 본 모든 마이그레이션 모듈은 node_save를 사용합니다.
Alfred Armstrong

1
@ blue928 그는 자신 사용 한다고 말하지만 Pathnode node_save() 모든 노드 저장 후 메뉴 캐시를 다시 작성하는 것과 같이 발생할 수있는 알려진 문제를 완화하는 코드를 추가합니다.
Clive

아, 알 겠어요 Bojan은 코드가 모듈이나 온라인에서 사용 가능하므로 경로 자동과 같은 병목 현상을 어떻게 처리했는지 볼 수 있습니까? xhprof와 좋은 생각입니다. 확인해 볼게요
blue928

5

우선, XCache / APC (PHP <5.5)를 설치하고 Drupal에 대해 memcached를 구성하십시오.

그런 다음 http://mysqltuner.pl에 있는 mysqltuner 스크립트를 사용하여 대량 쿼리에 대해 MySQL 구성을 최적화 할 수 있습니다 .

예 :

# 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를 최신 또는 상위 지점으로 업그레이드하십시오.
  • CPU에 따라 64 비트 이상의 아키텍처를 위해 PHP를 다시 컴파일
  • db 파일 또는 전체 LAMP 환경 (예 : SSD 또는 메모리 기반 파일 시스템 )에 더 빠른 저장 장치를 사용하십시오 .
  • 성능 병목 현상 (예 : XDebug Profiler , DTrace 또는 NuSphere PhpED PHP Profiler ) 을 찾으려면 PHP 디버거 또는 프로파일 러를 사용 하십시오.
  • gprof 프로파일 링 도구에서 시간이 많이 걸리는 drush 명령을 실행 하면 성능 병목 현상을 찾을 수 있습니다

1
MySQL 튜닝은 큰 차이를 만드는 것으로 보입니다. mysqltuner.pl에서 제공 한 팁을 따르면 약 80 node_saves에서 약 700으로 이동했습니다.
John McCollum

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.