web-dev-qa-db-fra.com

Les passagers sont-ils ramassés?

Cette question m'a fait réfléchir Les flux RSS transitoires dans wp_options ne sont pas automatiquement supprimés?

Les transitoires sont supposés expirer et être supprimés. Cependant, la seule façon de voir cela traité est lorsque le transitoire est expiré et demandé, puis il est supprimé lors de la demande.

Que se passe-t-il si le transitoire a expiré mais n'est jamais demandé après cela? D'après la description du Codex, je pensais qu'une sorte de ramasse-miettes est implicite. Maintenant, je ne suis pas si sûr et je ne trouve aucun code qui fonctionne de la sorte.

Alors, sera-t-il simplement bloqué dans la base de données pour toujours?

61
Rarst

Ils sont maintenant

À partir de WordPress 3.7, les transitoires expirés sont supprimés lors de la mise à niveau de la base de données, voir # 20316


Ancienne réponse

Si quelqu'un ne peut pas me montrer le contraire, il semble que les passagers ne soient pas ramassés après tout. Ce qui aggrave la situation, c'est que contrairement aux options, leur stockage dans la base de données n'est pas garanti. Il n’existe donc aucun moyen fiable d’extraire la liste de tous les transitoires pour vérifier leur expiration.

Quelques codes de fortune pour faire la récupération de place si la base de données est utilisée pour le stockage:

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);
    }
}
44
Rarst

Déplacement de certains commentaires de la discussion dans une réponse, avec reformulation et reformatage.

En gros, si on a un cas extrême, ils n'ont pas vraiment besoin d'être "ramassés les ordures". Si vous ne les récupérez jamais, peu importe qu'ils soient là ou non.

Voir, les transitoires sont stockés dans la table d'options par défaut. Dans une installation de base, la table d'options contiendra peut-être 100 entrées. Chaque transitoire ajoute deux entrées supplémentaires, mais même si vous en avez des milliers, elles n’affectent pas la vitesse du site, car elles ne sont pas chargées automatiquement.

Au démarrage, WordPress charge les options en mémoire, mais il ne charge que les options dont l'indicateur de chargement automatique est activé. Les passagers ne comprennent pas cela et ne sont donc pas chargés en mémoire. Seuls les transitoires qui seront effectivement utilisés plus tard entraîneront des coûts.

Du point de vue de la base de données, la table des options contient des index sur l’option Id et sur le nom de l’option. Les transitoires sont toujours chargés en fonction du nom (clé). Par conséquent, leurs recherches sont toujours simples et se font sur une seule valeur de clé. Ainsi, la recherche est O(log(n)) et est très rapide. Avec un Big-O de log (n), il faudrait entrer dans les millions et les millions de lignes avant que cela devienne perceptible. Franchement, le temps système nécessaire à la configuration et à la suppression de la requête, ainsi que le transfert des données, est beaucoup plus long. La requête elle-même s'exécute pratiquement à zéro heure par comparaison. Donc, simplement avoir les rangées inutilisées en plus n'affecte que l'utilisation d'espace disque supplémentaire.

L'indexation dans les bases de données est l'une de ces idées profondes qui n'a pas de sens pour ceux qui n'ont pas encore compris ce qui se passe dans les coulisses. Les bases de données sont conçues pour une récupération rapide des données, à partir de la base, et peuvent gérer ce genre de choses sans problèmes. C'est une très bonne lecture: http://en.wikipedia.org/wiki/Index_(database )

Désormais, le nettoyage de la manière la plus évidente (appeler SQL DELETE sur eux) ne les supprime pas réellement de la base de données. Il les supprime simplement de l'index et marque la ligne comme "supprimée". Encore une fois, c’est ainsi que fonctionnent les bases de données. Pour réellement libérer de l’espace disque, vous devez continuer et exécuter ensuite une table OPTIMIZE TABLE. Il ne s’agit pas d’une opération rapide. Ça prend du temps. Probablement plus de temps que ça en vaut la peine. Ce n'est probablement pas suffisant pour vous permettre d'économiser du temps processeur au total.

Si certains cas entraînent une insertion continue de nouveaux transitoires qui ne sont pas utilisés, vous devez alors rechercher le problème sous-jacent. Qu'est-ce que l'insertion de ces transitoires? Utilisent-ils une clé changeante ou en mutation? Si tel est le cas, le plug-in ou le code à l'origine de ce problème doit être corrigé pour ne pas le faire. Cela sera plus utile, car il est probable que le code qui ne les crée pas correctement ne les récupère pas non plus, ce qui représente plus de travail que nécessaire.

Par ailleurs, il peut arriver que des transitoires soient créés pour quelque chose comme toutes les publications. Cela peut en effet être parfaitement acceptable. Je le fais moi-même dans SFC, pour stocker les commentaires entrants de Facebook. Chaque publication est associée à un transitoire potentiel, ce qui signifie deux lignes supplémentaires par publication. Si vous avez 10k postes, vous aurez 20k lignes dans la table d'options (éventuellement). Ce n'est ni mauvais ni lent, car là encore, il y a très peu de différence entre 100 lignes et 20 000 lignes dans la mesure où les bases de données sont importantes. Tout est indexé. C'est rapide comme bonjour. Sous-sous-millisecondes.

Lorsque vous commencez à entrer dans millions de lignes, je suis inquiet. Lorsque la taille de la table d'options dépasse plusieurs centaines de mégaoctets, je serais suffisamment préoccupée pour examiner de plus près. Mais d’une manière générale, ce n’est pas un problème, sauf dans les cas extrêmes. Ce n’est certainement pas un problème pour des projets plus petits qu’un site comme un grand site d’informations, avec des centaines de milliers de messages. Et pour tout site suffisamment grand pour poser problème, vous devez utiliser un cache d’objets externe, et dans que cas, les éléments transitoires sont automatiquement stockés dans cette base plutôt que dans la base de données.

20
Otto

Otto - Je ne pourrais pas être plus en désaccord avec vous. Le problème est que finalement avec tous ces transitoires, la taille de la table devient ridicule. Il ne faut pas des millions de lignes pour s'enliser. Je traite actuellement avec une table d'options comportant plus de 130 000 lignes et qui se bloque régulièrement. Étant donné que le champ de valeur est un type de texte volumineux, même la recherche des lignes de "chargement automatique" devient un cauchemar de performances. Ces champs de valeur sont stockés séparément du reste des données de la ligne. Même si cela fait logiquement partie de la même table, des jointures doivent avoir lieu pour afficher les lignes souhaitées. Les jointures prennent maintenant une éternité car les données dont vous avez besoin sont réparties sur le disque. Le profilage (en utilisant jet profiler pour mysql) l'a prouvé.

L'ajout du chargement automatique à la clé en cluster peut aider à résoudre ce problème. Le regroupement sur Autoload Desc, ID ASC par exemple, permettrait à toutes les lignes de chargement automatique de se regrouper en premier sur le disque. Même quand même, je pense que vous envisagez une énorme pression du point de vue de la DB.

Personnellement, je pense que la conception de ce système est géniale. Le tableau des options semble s'être transformé en un fourre-tout général pour beaucoup de choses. C'est bien si le champ de valeur est suffisamment petit pour être inclus sur la même page que le reste du rowdata et peut être indexé efficacement. Malheureusement ce n'est pas le cas. Celui qui a conçu cela doit retourner à la classe DB101.

18
myke