Tengo un archivo csv que quiero insertar que consta de ~ 1,500 filas y 97 columnas. Se necesitan entre 2 y 3 horas para realizar una importación completa y me gustaría mejorar esto si hay alguna manera. Actualmente para cada fila estoy haciendo un $ post_id = wp_insert_post y luego un add_post_meta para las 97 columnas asociadas con cada fila. Esto es bastante ineficiente ...
¿Hay una mejor manera de hacer esto de una manera que pueda obtener un post_id para mantener la relación entre post y sus valores post_meta?
En este momento estoy probando esto en mi máquina local con wamp pero lo tendré funcionando en un VPS
wp-insert-post
Corey Rowell
fuente
fuente
Respuestas:
Hace algún tiempo tuve problemas similares con una importación CSV personalizada, pero terminé usando un SQL personalizado para la inserción masiva. Pero no había visto esta respuesta para entonces:
¿Optimizar la inserción y eliminación de publicaciones para operaciones masivas?
para
wp_defer_term_counting()
habilitar o deshabilitar el conteo de términos.Además, si revisa la fuente del complemento importador de WordPress, verá estas funciones justo antes de la importación masiva:
y luego después de la inserción masiva:
Entonces esto podría ser algo para probar ;-)
Importar publicaciones como borrador en lugar de publicar también acelerará las cosas, ya que se omite el lento proceso de encontrar una babosa única para cada una. Uno podría, por ejemplo, publicarlos más tarde en pasos más pequeños, pero tenga en cuenta que este tipo de enfoque necesitaría marcar las publicaciones importadas de alguna manera, ¡así que no publicaremos ningún borrador más adelante! Esto necesitaría una planificación cuidadosa y muy probablemente una codificación personalizada.
Si, por ejemplo, se importan muchos títulos de publicaciones similares (iguales
post_name
),wp_unique_post_slug()
puede volverse lento, debido a la iteración de la consulta de bucle para encontrar una babosa disponible. Esto posiblemente puede generar una gran cantidad de consultas db.Desde WordPress 5.1, el
pre_wp_unique_post_slug
filtro está disponible para evitar la iteración del bucle de la babosa. Ver boleto principal # 21112 . Aquí hay un ejemplo:Si uno intenta, por ejemplo,
$override_slug = _truncate_post_slug( $slug, 200 - ( strlen( $suffix ) + 1 ) ) . "-$suffix"
con$suffix
as$post_id
, entonces notaríamos que$post_id
siempre es0
para nuevas publicaciones, como se esperaba. Sin embargo, hay varias formas de generar números únicos en PHP, comouniqid( '', true )
. Pero use este filtro con cuidado para asegurarse de tener babosas únicas. Podríamos, por ejemplo, ejecutar una consulta de recuento grupal despuéspost_name
para estar seguros.Otra opción sería usar WP-CLI para evitar el tiempo de espera. ¿Ve, por ejemplo, mi respuesta publicada para Crear 20,000 publicaciones o páginas usando un archivo .csv?
Luego podemos ejecutar nuestro script de importación PHP personalizado
import.php
con el comando WP-CLI:También evite importar una gran cantidad de tipos de publicaciones jerárquicas, ya que la interfaz de usuario actual de wp-admin no lo maneja bien. Ver, por ejemplo, tipo de publicación personalizada - lista de publicaciones - pantalla blanca de la muerte
Aquí está el gran consejo de @otto:
Antes de las inserciones masivas , deshabilite el
autocommit
modo explícitamente:Después de las inserciones masivas, ejecute:
También creo que sería una buena idea hacer algunas tareas de limpieza como:
No he probado esto en MyISAM pero debería funcionar en InnoDB .
Como mencionó @kovshenin, este consejo no funcionaría para MyISAM .
fuente
SET autocommit=0;
antes de las inserciones, seguido de unCOMMIT;
después.$wpdb->query('SET autocommit = 0;');
antes de las inserciones, pero ¿podemos omitir$wpdb->query('START TRANSACTION;');
en ese caso? Revisaré el manual de MySQL para obtener más información al respecto ;-) saludos.wp_suspend_cache_addition( true )
NO debería ayudar a poner cosas en el caché de objetos. También @birgire mencionó que no probaron esto con MyISAM; no se moleste, el motor de almacenamiento no admite transacciones, por lo que configurar la confirmación automática o iniciar una transacción no tendrá ningún efecto.Deberá insertar la publicación para obtener su ID, pero la
$wpdb->postmeta
tabla tiene una estructura muy simple. Probablemente podría usar unaINSERT INTO
declaración directa , como esta de los documentos de MySQL:INSERT INTO tbl_name (a,b,c) VALUES(1,2,3),(4,5,6),(7,8,9);
En tu caso...
Eso no se ocupará de ninguna codificación, serialización, escape, verificación de errores, duplicaciones o cualquier otra cosa, pero esperaría que fuera más rápido (aunque no lo he intentado).
No haría esto en un sitio de producción sin una prueba exhaustiva, y si solo tuviera que hacerlo una o dos veces, usaría las funciones principales y tomaría un largo almuerzo mientras las cosas se importan.
fuente
->prepare()
sus declaraciones SQL. En su escenario, ¿qué pasaría si la columna de ID en el CSV contuviera algo así1, 'foo', 'bar'); DROP TABLE wp_users; --
? Algo malo probablemente.Tuve que agregar esto:
Tenga en cuenta que esto saltará
do_all_pings
, lo que procesa pingbacks, recintos, trackbacks y otros pings (enlace: https://developer.wordpress.org/reference/functions/do_all_pings/ ). Segúnremove_action
tengo entendido al mirar el código, los pingbacks / trackbacks / recintos pendientes aún se procesarán después de eliminar esta línea, pero no estoy completamente seguro.Actualización: también agregué
Más allá de eso estoy usando:
fuente
Nota importante sobre
'SET autocommit = 0;'
después de configurar
autocommit = 0
si el script detiene la ejecución (por alguna razón, como unexit
error fatal o etc.), entonces sus cambios NO SE GUARDARÁN EN DB!¡En este caso
update_option
no se guardará en DB!Por lo tanto, el mejor consejo es haberse
COMMIT
registrado enshutdown
función como precaución (en caso de que ocurra una salida inesperada).fuente