Eu tenho um arquivo CSV que eu quero inserir que consiste em ~ 1.500 linhas e 97 colunas. Demora cerca de 2-3 horas para fazer uma importação completa e eu gostaria de melhorar isso, se houver uma maneira. Atualmente, para cada linha, estou fazendo um $ post_id = wp_insert_post e, em seguida, um add_post_meta para as 97 colunas associadas a cada linha. Isso é bastante ineficiente ...
Existe uma maneira melhor de fazer isso de uma maneira que um post_id possa manter o relacionamento entre post e seus valores post_meta?
No momento, estou tentando fazer isso na minha máquina local com wamp, mas o executarei em um VPS
wp-insert-post
Corey Rowell
fonte
fonte
Respostas:
Eu tive problemas semelhantes há algum tempo com uma importação CSV personalizada, mas acabei usando algum SQL personalizado para a inserção em massa. Mas eu não tinha visto essa resposta até então:
Otimizar pós-inserção e exclusão para operações em massa?
para
wp_defer_term_counting()
ativar ou desativar a contagem de termos.Além disso, se você verificar a fonte do plug-in importador do WordPress, verá estas funções imediatamente antes da importação em massa:
e depois da inserção em massa:
Portanto, isso pode ser algo para experimentar ;-)
A importação de postagens como rascunho, em vez de publicação , também acelerará as coisas, pois o processo lento de encontrar uma lesma exclusiva para cada uma é ignorado. Pode-se, por exemplo, publicá-las posteriormente em etapas menores, mas observe que esse tipo de abordagem precisaria marcar as postagens importadas de alguma forma, para que não publicemos apenas os rascunhos posteriormente! Isso exigiria um planejamento cuidadoso e provavelmente uma codificação personalizada.
Se houver, por exemplo, muitos títulos de postagem semelhantes (iguais
post_name
) a serem importados,wp_unique_post_slug()
pode ficar lento, devido à iteração da consulta de loop para encontrar uma lesma disponível. Isso pode gerar um grande número de consultas de banco de dados.Desde o WordPress 5.1, o
pre_wp_unique_post_slug
filtro está disponível para evitar a iteração de loop da lesma. Veja o tíquete principal # 21112 . Aqui está um exemplo:Se alguém tentar, por exemplo,
$override_slug = _truncate_post_slug( $slug, 200 - ( strlen( $suffix ) + 1 ) ) . "-$suffix"
com$suffix
as$post_id
, notaremos que$post_id
é sempre0
para novas postagens, como esperado. Existem várias maneiras de gerar números únicos em PHP, comouniqid( '', true )
. Mas use esse filtro com cuidado para garantir que você tenha lesmas exclusivas. Por exemplo, poderíamos executar uma consulta de contagem de grupos posteriormentepost_name
para ter certeza.Outra opção seria usar o WP-CLI para evitar o tempo limite. Veja, por exemplo, minha resposta publicada em Criando 20.000 postagens ou páginas usando um arquivo .csv?
Em seguida, podemos executar nosso script de importação PHP personalizado
import.php
com o comando WP-CLI:Evite também importar um grande número de tipos hierárquicos de postagem, pois a atual interface do usuário wp-admin não lida bem com isso. Veja, por exemplo, tipo de publicação personalizada - lista de publicações - tela branca da morte
Aqui está a ótima dica do @otto:
Antes das inserções em massa , desative o
autocommit
modo explicitamente:Após as inserções em massa, execute:
Também acho que seria uma boa ideia fazer algumas tarefas domésticas, como:
Eu não testei isso no MyISAM, mas isso deve funcionar no InnoDB .
Como mencionado por @kovshenin, essa dica não funcionaria para o MyISAM .
fonte
SET autocommit=0;
antes das inserções, seguido por umCOMMIT;
depois.$wpdb->query('SET autocommit = 0;');
antes das inserções, mas podemos pular$wpdb->query('START TRANSACTION;');
nesse caso? Vou verificar o manual do MySQL para aprender mais sobre ele ;-) aplausos.wp_suspend_cache_addition( true )
NÃO deve ajudar a colocar coisas no cache do objeto. Além disso, a @birgire mencionou que não testou isso com o MyISAM - não se preocupe, o mecanismo de armazenamento não suporta transações, portanto, configurar o autocommit ou iniciar uma transação terá efeito zero.Você precisará inserir a postagem para obter seu ID, mas a
$wpdb->postmeta
tabela é muito simples em estrutura. Você provavelmente poderia usar umaINSERT INTO
declaração direta , como esta nos documentos do MySQL:INSERT INTO tbl_name (a,b,c) VALUES(1,2,3),(4,5,6),(7,8,9);
No seu caso...
Isso não lida com codificação, serialização, escape, verificação de erros, duplicações ou qualquer outra coisa, mas espero que seja mais rápido (embora ainda não tenha tentado).
Eu não faria isso em um local de produção sem testes completos e, se tivesse que fazê-lo uma ou duas vezes, usaria as funções principais e almoçaria enquanto as coisas importam.
fonte
->prepare()
suas instruções SQL. No seu cenário, o que aconteceria se a coluna ID no CSV contivesse algo como1, 'foo', 'bar'); DROP TABLE wp_users; --
? Algo ruim, provavelmente.Eu tive que adicionar isso:
Lembre-se de que isso será ignorado
do_all_pings
, o que processa pingbacks, gabinetes, trackbacks e outros pings (link: https://developer.wordpress.org/reference/functions/do_all_pings/ ). Meu entendimento ao analisar o código é que os pingbacks / trackbacks / gabinetes pendentes ainda serão processados após a remoção destaremove_action
linha, mas não tenho certeza.Atualização: eu também adicionei
Além do que estou usando:
fonte
Nota importante sobre
'SET autocommit = 0;'
após definir
autocommit = 0
se o script interrompe a execução (por algum motivo, comoexit
erro fatal ou etc ...), suas alterações NÃO SERÃO SALVAS NO DB!Nesse caso
update_option
, não será salvo no DB!Portanto, o melhor conselho é ter se
COMMIT
registradoshutdown
como uma precatuação (no caso de uma saída inesperada).fonte