У меня есть файл CSV, который я хочу вставить, который состоит из ~ 1500 строк и 97 столбцов. Полный импорт занимает около 2-3 часов, и я хотел бы улучшить это, если есть способ. В настоящее время для каждой строки я делаю $ post_id = wp_insert_post и затем add_post_meta для 97 связанных столбцов с каждой строкой. Это довольно неэффективно ...
Есть ли лучший способ сделать это так, чтобы a post_id мог сохранить связь между post и его значениями post_meta?
Прямо сейчас я пытаюсь это на моей локальной машине с Wamp, но будет работать на VPS
wp-insert-post
Кори Роуэлл
источник
источник
Ответы:
Когда-то у меня были похожие проблемы с пользовательским импортом в CSV, но в итоге я использовал некоторый пользовательский SQL для массовой вставки. Но я не видел этот ответ к тому времени:
Оптимизировать пост вставки и удаления для массовых операций?
использовать,
wp_defer_term_counting()
чтобы включить или отключить подсчет сроков.Также, если вы проверите источник для плагина импорта WordPress, вы увидите эти функции непосредственно перед массовым импортом:
а затем после основной вставки:
Так что это может быть что-то попробовать ;-)
Импорт сообщений в виде черновика вместо публикации также ускорит процесс, поскольку медленный процесс поиска уникального слагаемого для каждого из них пропускается. Можно, например, опубликовать их позже небольшими шагами, но учтите, что при таком подходе нужно каким-то образом пометить импортированные записи, поэтому мы не будем публиковать черновики позже! Это потребует тщательного планирования и, скорее всего, некоторого пользовательского кодирования.
Если, например,
post_name
нужно импортировать много похожих заголовков (одинаковых ), то этоwp_unique_post_slug()
может замедлиться из-за итерации цикла, чтобы найти доступную порцию. Это может генерировать огромное количество запросов БД.Начиная с WordPress 5.1,
pre_wp_unique_post_slug
фильтр доступен, чтобы избежать итерации цикла для слага. Смотрите основной билет # 21112 . Вот пример:Если вы попробуете, например,
$override_slug = _truncate_post_slug( $slug, 200 - ( strlen( $suffix ) + 1 ) ) . "-$suffix"
с$suffix
as$post_id
, то мы бы отметили, что$post_id
всегда0
для новых сообщений, как и ожидалось. Существуют различные способы генерирования уникальных чисел в PHP, напримерuniqid( '', true )
. Но используйте этот фильтр осторожно, чтобы убедиться, что у вас есть уникальные слизни. Мы могли бы, например, запустить запрос на подсчет группы потом,post_name
чтобы быть уверенным.Другой вариант - использовать WP-CLI, чтобы избежать тайм-аута. См., Например, мой ответ, опубликованный для создания 20000 сообщений или страниц с использованием файла .csv?
Затем мы можем запустить наш собственный скрипт импорта PHP
import.php
с помощью команды WP-CLI:Также избегайте импорта большого количества иерархических типов записей, так как текущий пользовательский интерфейс wp-admin плохо с этим справляется. См. Например, Пользовательский тип сообщения - список сообщений - белый экран смерти
Вот отличный совет от @otto:
Перед массовыми вставками отключите
autocommit
режим явно:После массовых вставок запустите:
Я также думаю, что было бы неплохо заняться уборкой, например:
Я не проверял это на MyISAM, но это должно работать на InnoDB .
Как упомянул @kovshenin, этот совет не сработает для MyISAM .
источник
SET autocommit=0;
перед вставками, а затемCOMMIT;
после.$wpdb->query('SET autocommit = 0;');
до вставки, но мы можем пропустить$wpdb->query('START TRANSACTION;');
в этом случае? Я проверю руководство MySQL, чтобы узнать больше об этом ;-) ура.wp_suspend_cache_addition( true )
должно помочь НЕ помещать вещи в кеш объекта. Кроме того, @birgire упомянул, что они не проверяли это с MyISAM - не беспокойтесь, механизм хранения не поддерживает транзакции, поэтому установка автоматической фиксации или запуск транзакции будут иметь нулевой эффект.Вам нужно будет вставить сообщение, чтобы получить свой идентификатор, но
$wpdb->postmeta
таблица очень проста по структуре. Возможно, вы могли бы использовать прямоеINSERT INTO
утверждение, например, из документации MySQL:INSERT INTO tbl_name (a,b,c) VALUES(1,2,3),(4,5,6),(7,8,9);
В твоем случае...
Это не касается кодирования, сериализации, экранирования, проверки ошибок, дублирования или чего-либо еще, но я ожидаю, что это будет быстрее (хотя я не пробовал).
Я бы не стал делать это на производственной площадке без тщательного тестирования, и если бы мне нужно было сделать это один или два раза, я бы использовал основные функции и долго обедал, пока что-то импортировалось.
источник
->prepare()
ваши операторы SQL. В вашем сценарии, что произойдет, если в столбце идентификаторов в CSV будет что-то подобное1, 'foo', 'bar'); DROP TABLE wp_users; --
? Что-то плохое, наверное.Я должен был добавить это:
Имейте в виду, что это будет пропускать
do_all_pings
, который обрабатывает pingbacks, вложения, trackbacks и другие ping (ссылка: https://developer.wordpress.org/reference/functions/do_all_pings/ ). Насколько я понимаю, глядя на код, можно ожидать, что ожидающие pingbacks / trackbacks / вложений будут обрабатываться после удаления этойremove_action
строки, но я не совсем уверен.Обновление: я также добавил
Помимо этого я использую:
источник
Важное замечание о
'SET autocommit = 0;'
после установки,
autocommit = 0
если сценарий останавливает выполнение (по какой-то причине, напримерexit
, из-за фатальной ошибки или т. д.), ваши изменения НЕ БУДУТ СОХРАНЕНЫ в БД!В этом случае
update_option
не будет сохранен в БД!Итак, лучший совет -
COMMIT
зарегистрироваться вshutdown
функции в качестве предупреждения (на случай, если произойдет какой-либо неожиданный выход).источник