Як я можу пришвидшити функцію node_save () drupal?


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

Ось результати:

Було збережено 100 000 вузлів, кожен з яких використовує node_save (). На завершення пішло 5196,22 секунди. Тобто ТОЛЬко 19 економить секунду.

Як мінімум, це не прийнятно, особливо коли ця людина отримує близько 1200 індивідуальних запитів вставки в секунду , і ця людина отримує 25000 вставок в секунду .

Отже, що тут відбувається? Де вузьке місце? Це функція node_save () і як вона розроблена?

Може це моє обладнання? Моє обладнання - це сервер розробки, на ньому ніхто, крім мене - двоядерний Intel, 3 ГГц, Ubuntu 12.04 з 16 гігами оперативної пам’яті.

У той час як цикл працює, моє використання ресурсів: MySQL 27% CPU, 6M RAM; PHP 22% CPU 2M оперативної пам'яті.

Мою конфігурацію mysql виконав майстер percona .

Mysql каже, що якщо моє використання процесора менше 70%, моя проблема пов'язана з диском . Звичайно, у мене є лише пробіг млини WD Caviar 7200 RPM, але я маю отримувати більше 19 вставок в секунду з нею, сподіваюся!

Не так давно я писав про економію 30 000 вузлів за день . Однак, щоб бути зрозумілим, цей вузол не має нічого спільного з будь-якими зовнішніми силами. Це суто орієнтир, щоб дізнатися, як збільшити швидкість дзвінків до node_save ().

Реально мені потрібно щомісяця заносити 30 000 елементів у базу даних за допомогою node_save. Якщо збереження вузла - це не варіант, мені цікаво, чи можу я написати власну функцію drupal api "node_batch_save ()" або щось, що використовує можливість mysql робити об'ємні вставки за допомогою INSERT-запиту . Думки про те, як до цього підійти?


2
Існує велика різниця між продуктивністю необробленої вставки та тим, що робитиме node_save. Для одного node_save виконує серію читання та запису. Але немає сенсу обговорювати можливі вузькі місця та оптимізацію без додаткових даних.
Альфред Армстронг

Вам потрібно врахувати, чому ви використовуєте Drupal таким чином у своїх цілях. Якщо ви просто хочете зафіксувати велику кількість даних у плоскій таблиці та відобразити їх за допомогою Drupal, ви, можливо, захочете взагалі обійти Drupal під час їх запису і використовувати спеціальний модуль для інтеграції даних за допомогою Views тощо.
Альфред Армстронг,

Сумніваюсь, що горловина пляшки знаходиться на базі даних. Збереження вузла робить багато речей у фоновому режимі: він викликатиме ряд гачків (гак_нод_пресав, гак_енті_пресав, гак_ноде_інсерт, гак_енті_інсерт тощо), кожен з яких може викликати будь-яку кількість модулів. Крім того, node_save відновить дозволи для цього вузла, і він очистить кеш для цього вузла ...
Аліса Хітон

@AlfredArmstrong Я створюю вузли на основі даних, що знаходяться в іншій базі даних. Я формую дані до правильного типу вмісту drupal і node_save їх. Мої клієнти - це переважно університети, які хочуть перейти на drupal. Не рідкість для них є від 200 000 до 1 000 000 вузлів (вміст веб-сайтів, записи студентів та викладачів тощо), на які вони хотіли б перенести через десятиліття використання власних веб-рішень. Я читаю це, що є обнадійливим, але все ж менш бажаним підходом. evolvingweb.ca/story / ...
blue928

.. тож я вважаю за краще залишитися якомога дружніше. Використання збереження вузла з великою кількістю даних забезпечує цілісність. Якщо я не можу так працювати, я готовий займатися творчістю.
blue928

Відповіді:


10

Ви ніколи не отримаєте 30 000 вставок за хвилину, використовуючи node_save. У жодному разі.

ВСТАВКА швидка, тому що це все, що вона робить. Збереження вузла робить кілька вставок (основна таблиця, таблиця редагувань, таблиця для кожного поля), очищає кеші будь-яких об'єктів і запускає гачки. Гачки - це хитра частина. Якщо у вас є багато модулів для внесків (або навіть таких, що недобре поводяться), які дійсно можуть знищити продуктивність, особливо якщо автор не брав до уваги "Я заощаджую тону вузлів відразу". Наприклад, мені довелося додати це до свого класу 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.
Альфред Армстронг

1
@ blue928 Він каже, що використовує node_save(), але додає код, щоб зменшити відомі проблеми, які можуть бути викликані, як, наприклад, Патхауто перебудовує кеш меню після кожного збереження вузла
Clive

ах, добре, я бачу. Bojan - ваш код доступний у модулі чи в Інтернеті, де я міг бачити, як ви мали справу з вузькими місцями, як автодоріжка шляху? Гарна ідея з xhprof. Я перевірю це.
blue928

5

Перш за все, встановіть XCache / APC (для PHP <5.5) та налаштуйте запам’ятоване для Drupal.

Тоді ви можете оптимізувати конфігурацію MySQL для важких запитів, використовуючи скрипт mysqltuner, доступний за адресою: 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-розрядної або вище архітектури залежно від вашого процесора,
  • використовувати швидший пристрій зберігання даних для своїх db-файлів або всього середовища LAMP (наприклад, SSD або файлової системи на основі пам'яті ),
  • використовуйте налагоджувач PHP або профілер, щоб дізнатись про якісь вузькі місця (наприклад, XDebug Profiler , DTrace або NuSphere PhpED PHP Profiler ),
  • запустити деяку трудомістку команду Drush під дргіМ профилированием інструменту, так що ви можете знайти деякі продуктивності вузьких місць, а також

1
Налаштування MySQL має велике значення. Я пройшов приблизно від 80 node_saves хвилини до 700, лише дотримуючись порад, наданих mysqltuner.pl.
Джон Макколлум

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.