Os transientes são coletados com lixo?

58

Essa pergunta me fez pensar Feeds RSS transientes em wp_options não foi removido automaticamente?

Os transientes devem expirar e ser excluídos. No entanto, a única maneira de ver isso é quando o transiente é expirado e solicitado e, em seguida, é excluído durante a solicitação.

E se o transitório expirar, mas nunca foi solicitado depois disso? A partir da descrição no Codex, pensei que algum tipo de coleta de lixo está implícito. Agora eu não tenho tanta certeza e não consigo encontrar nenhum código que faça isso.

Então, ele ficará preso no banco de dados para sempre?

    
por Rarst 09.01.2011 / 01:20
fonte

3 respostas

42

Eles agora são

A partir do WordPress 3.7, os transientes expirados são excluídos nas atualizações do banco de dados, consulte # 20316

Resposta antiga

Se alguém não puder me mostrar o contrário, parece que os transientes não são lixo coletado, afinal. O pior é que, ao contrário das opções, não é garantido que elas sejam armazenadas no banco de dados. Portanto, não há uma maneira confiável de buscar a lista de todos os transientes para verificar sua expiração.

Algum código improvisado para fazer coleta de lixo, se o banco de dados for usado para armazenamento:

add_action( 'wp_scheduled_delete', 'delete_expired_db_transients' );

function delete_expired_db_transients() {

    global $wpdb, $_wp_using_ext_object_cache;

    if( $_wp_using_ext_object_cache )
        return;

    $time = isset ( $_SERVER['REQUEST_TIME'] ) ? (int)$_SERVER['REQUEST_TIME'] : time() ;
    $expired = $wpdb->get_col( "SELECT option_name FROM {$wpdb->options} WHERE option_name LIKE '_transient_timeout%' AND option_value < {$time};" );

    foreach( $expired as $transient ) {

        $key = str_replace('_transient_timeout_', '', $transient);
        delete_transient($key);
    }
}
    
por Rarst 10.01.2011 / 10:55
fonte
20

Movendo alguns dos comentários da discussão para uma resposta, com reformulação e nova formatação.

Basicamente, o que acontece é que, a menos que você tenha um caso extremamente extremo, ele não precisa ser "coletado como lixo". Se você nunca os busca, então não importa se eles estão lá ou não.

Veja, os transientes são armazenados na tabela de opções por padrão. Em uma instalação básica, a tabela de opções terá talvez 100 entradas. Cada transiente adiciona mais duas entradas, mas mesmo se você tiver milhares, elas não afetam a velocidade do site, pois elas não são carregadas automaticamente.

Na inicialização, o WordPress carrega as opções na memória, mas só carrega opções que têm seu sinalizador de carregamento automático ativado. Os transientes não entendem isso e, portanto, não são carregados na memória. Somente transientes que são usados mais tarde incorrerão em um custo.

Da perspectiva do banco de dados, a tabela de opções possui índices na Id da opção e no nome da opção. Os transientes são sempre carregados com base no nome (chave) e, portanto, as pesquisas para eles são sempre simples e selecionáveis em um único valor de chave exclusivo. Assim, a pesquisa é O (log (n)) e é super rápida. Com um Big-O de log (n), você teria que entrar nos milhões e milhões de linhas antes que se tornasse perceptível. Francamente, a sobrecarga na configuração e desmontagem da consulta, juntamente com a transferência de dados real, é muito mais longa. A consulta em si é executada essencialmente em tempo zero por comparação. Então, simplesmente ter linhas extras não usadas não afeta nada, mas usar espaço extra em disco.

A indexação em bancos de dados é uma daquelas ideias de leitura profunda que não faz sentido para pessoas que não entenderam o que está acontecendo nos bastidores. Bancos de dados são projetados para recuperação rápida de dados, desde o início, e podem lidar com esse tipo de coisa sem problemas. Esta é uma boa leitura: enlace )

Agora, a limpeza da maneira mais óbvia (chamando SQL DELETE neles) não os exclui do banco de dados. Apenas os remove do índice e marca a linha como "excluída". Novamente, é assim que funcionam os bancos de dados. Para realmente limpar o espaço em disco, você tem que continuar e fazer um OPTIMIZE TABLE depois, e esta não é uma operação rápida. Leva tempo. Provavelmente mais tempo do que vale a pena. Provavelmente não é o suficiente para economizar no tempo de CPU, no total.

Se você tiver algum caso que esteja causando uma inserção contínua de novos transientes que não estão sendo usados, será necessário localizar o problema subjacente. O que está inserindo esses transientes? Eles estão usando uma chave de mudança ou mutação? Se assim for, então o plugin ou código causando isso deve ser corrigido para, basicamente, não fazer isso. Isso será mais útil, porque é provável que o código que não está sendo criado corretamente também não os recupere e, portanto, faça mais trabalho do que o necessário.

Por outro lado, pode haver um caso em que os transientes estão sendo criados para algo como cada postagem. Isso pode de fato ser perfeitamente aceitável. Eu faço isso sozinho no SFC, para armazenar os comentários recebidos do Facebook. Cada postagem tem um potencial transiente associado a ela, o que significa duas linhas extras por postagem. Se você tiver 10k posts, você terá 20k linhas na tabela de opções (eventualmente). Isso não é ruim ou lento, porque, novamente, há muito pouca diferença entre 100 linhas e 20.000 linhas, na medida em que os bancos de dados realmente se importam. Está tudo indexado. É rápido como o inferno. Sub-sub-milissegundos.

Quando você começa a entrar em milhões de linhas, então eu ficaria preocupado. Quando o tamanho da tabela de opções aumenta acima de centenas de megabytes, eu ficaria preocupado o suficiente para dar uma olhada mais de perto. Mas de um modo geral, isso não é um problema, exceto em casos extremos. Certamente não é um problema para algo menor do que algo como um grande site de notícias, com centenas de milhares de posts. E para qualquer site grande o suficiente para que seja um problema, você deve estar usando um cache de objeto externo de algum tipo, e em esse caso, os transientes ficam automaticamente armazenados lá em vez de no banco de dados. / p>     

por Otto 12.09.2011 / 20:09
fonte
17

Otto - Eu não poderia discordar mais de você. A questão é que, eventualmente, com todos esses transientes, o tamanho da tabela se torna ridículo. Não é preciso milhões de linhas para atolar. Atualmente estou lidando com uma tabela de opções que tem mais de 130k linhas e trava regularmente. Como o campo de valor é um tipo de texto grande, até procurar apenas as linhas "autoload" torna-se um pesadelo de desempenho. Esses campos de valor são armazenados separadamente do restante dos dados da linha. Embora seja logicamente parte da mesma tabela, as junções devem acontecer para exibir as linhas desejadas. Junções que agora demoram para sempre porque os dados que você precisa estão espalhados por todo o disco. Profiling (usando o jet profiler para o mysql) provou isso.

Adicionar carga automática à chave em cluster pode ajudar a resolver esse problema. Clustering on Autoload Desc, ID ASC, por exemplo, permitiria que todas as linhas de autoload fossem agrupadas primeiro no disco. Mesmo assim, acho que você está olhando para uma grande tensão do ponto de vista do DB.

Pessoalmente, acho que o design desse sistema é maluco. A tabela de opções parece ter se tornado geral para muitas coisas. Isso é bom se o campo de valor for pequeno o suficiente para ser incluído na mesma página que o restante dos dados de linha e pode ser indexado de forma eficaz. Infelizmente não é esse o caso. Quem projetou isso precisa voltar para a classe DB101.

    
por myke 02.12.2011 / 20:43
fonte