Construindo um plugin escalável que favorece o Wordpress - uma matriz de valor meta serializado ou muitos metadados

4

Estou tentando criar um plug-in de postagem favorito do Wordpress que seja escalonável e possa lidar com milhares de usuários ou 10000s ou mais.

Existem várias abordagens diferentes que vi em outros plugins e gostaria de saber qual seria a melhor prática do ponto de vista da escalabilidade, o que significa que o tamanho do registro ou o número de registros pode ser um problema.

Problema: A idéia básica é que há um botão em uma postagem na qual um usuário conectado pode clicar para a postagem favorita. Isso deve ser armazenado no banco de dados para que, quando o usuário for para o post, ele não possa favoritos novamente e também possa visualizar uma lista de suas postagens favoritas.

Opção 1: armazenar em tabelas meta e pós-meta de usuário com matrizes serializadas

Isto é o que o Sistema Wordpress Post Like ( enlace ) faz. Após o clique, o código recupera a meta key _liked_posts da meta-tabela do usuário que armazena em uma matriz os IDs das postagens que o usuário gostou e recupera a meta-chave _user_likes da meta-tabela de postagens que armazena em uma matriz ids dos usuários que curtiram a postagem.

O código então anexa o ID da postagem atual ao _liked_posts e o ID do usuário atual para _user_likes. Ele também incrementa mais dois metadados: postar como contagem e um usuário como contagem.

O que eu gosto neste sistema é que parece bastante simples, com apenas um registro no meta do usuário e um registro no armazenamento pós-meta que gostou do quê. O que eu não gosto é que, se você tem muitos usuários curtindo o post ou um usuário que gosta de muitos posts, esses arrays de meta valor podem ficar muito longos, o que eu suponho poderia causar problemas?

$meta_POSTS = get_user_meta( $user_id, "_liked_posts" ); // post ids from user meta
$meta_USERS = get_post_meta( $post_id, "_user_liked" ); // user ids from post meta
$meta_POSTS['post-'.$post_id] = $post_id; // Add post id to user meta array
$meta_USERS['user-'.$user_id] = $user_id; // add user id to post meta array
update_post_meta( $post_id, "_user_liked", $meta_USERS ); // Add user ID to post meta
update_user_meta( $user_id, "_liked_posts", $meta_POSTS ); // Add post ID to user meta

Opção 2: adicionar um registro à meta do usuário para cada postagem curtida

Após o clique, o código verifica se um registro já foi inserido na meta do usuário. Caso contrário, adiciona um novo registro do favorito. Se tiver, não faz nada.

O que eu gosto nesse sistema é que é fácil consultar e gerar estatísticas no futuro, já que ele não está vinculado a matrizes serializadas. O que eu não gosto é que, se você tem o usuário gostando de muitas postagens, você pode aumentar enormemente o número de registros na tabela meta do usuário.

// Check if already favourited the post in User Meta
// Not sure how you would do this with WP_Query or WP_User_Query, any suggestions?

$favourited = WP_Query($args)

if ($favourited->post_count == 0) {
  // Add user meta with favourite
  add_user_meta($userid, '_favourite_episode', $postid);
}

Então, para concluir, o que eu estou pedindo, essencialmente, é o que é melhor prática aqui. Ou é:

  • Ter um grande array serializado em um único par meta / chave meta
  • Ter muitos pares de valores meta / chave com um inteiro no valor meta
  • Existe outra opção que não considerei?

EDITAR: Após as respostas dadas, decidi que criar uma tabela personalizada é o melhor caminho a seguir. Eu encontrei este tutorial que faz muito bem o que eu quero fazer e de uma forma muito mais extensível, para que eu possa adicionar outras ações, bem como apenas 'favouriting'.

enlace

    
por Alex 03.04.2016 / 17:39

2 respostas

4

Você esqueceu a opção 3 - Adicione uma tabela especial na qual o par (usuário, ID de postagem) será o índice. Ok, eu não sou uma pessoa do MySQL, então talvez seja muito radical, mas talvez ter duas tabelas, uma com usuários como índice e outra com posts, seja ainda melhor.

A coisa sobre o desempenho é que raramente existem soluções absolutas para todos, a qualquer momento, e o "melhor" depende do seu padrão de uso real, não do teórico. Ou, em outras palavras, você está fazendo otimização antecipada aqui.

Embora a opção 2 pareça ser mais rápida para essa informação específica, ela tornará as tabelas meta maiores e, portanto, provavelmente reduzirá as todas solicitações para essas tabelas (portanto, a sugestão para a opção 3 é muito semelhante, mas não afeta outras consultas).

Outro problema que você ignora aqui é o custo de inserir / atualizar dados. Esta operação é muito mais lenta do que uma leitura e não pode ser armazenada em cache. Se você tiver muitos likes ao mesmo tempo, com a opção 2 você bloqueará as tabelas e as solicitações precisarão aguardar a conclusão de outros e cada inserção será mais lenta, enquanto a opção 1 provavelmente terminará em corrupção de dados sob implementação ingênua (duas mudanças no mesmo tempo, na melhor das hipóteses, apenas uma delas terá impacto).

E então você deve levar em consideração que tipo de cache você fará. Com um bom esquema de cache, o tempo de leitura não é um problema.

Para concluir, desejo que você ache que este é um problema real que precisa ser resolvido, até que basta escrever uma api adequada para acessar / alterar esses dados para ocultar os detalhes da implementação, para que se torne um problema. capaz de alterar a implementação sem afetar o resto do seu código.

    
por Mark Kaplun 03.04.2016 / 18:21
0

Opção 1 não é a melhor escolha porque a serialização de dados significa que você deve analisar seu resultado de SQL para ser legível e, portanto, não pode tirar vantagem de consultas SQL.

A opção 2 seria a maneira mais fácil, mas se você tem muitos usuários que estão gostando de muitas postagens, então ela começa a poluir a meta-tabela do usuário.

Opção 3 o que eu faria, é criar tabela relacional entre posts e usuários. Usar tabela de relações seria o mais fácil, porque você pode usar o SQL para fazer muita lógica para você. Por exemplo, você não precisa contar quantos likes tem um post no PHP, mas sim executar uma consulta no SQL que faz isso para você e retorna o resultado. Isso significa que será bom para o desempenho e se você desinstalar o plug-in, tudo o que você precisa fazer é remover a tabela, simples e limpa.

    
por Marttin Notta 03.04.2016 / 17:54