web-dev-qa-db-fra.com

Manière correcte d'exécuter une requête de base de données non susceptible de mise en cache

Considérons le code

function getNow() {
    global $wpdb;

    $now = $wpdb->get_var("SELECT NOW()");

    $wpdb->flush();

    return $now;
}

J'utilise la méthode ci-dessus pour éviter l'effet de mise en cache de la méthode get_var lorsque j'exécute la fonction. J'obtiens toujours le même résultat, par exemple.

echo getNow();
sleep(10);
echo getNow(); // Same result as above

Des questions:

  1. Existe-t-il un meilleur moyen d'écrire la fonction ci-dessus pour éviter l'effet de mise en cache?
  2. Pourquoi $wpdb SEULEMENT cache-t-il le dernier résultat mais pas le résultat de toutes les requêtes dans la même requête? Cela semble un peu exagéré pour la dernière requête, non?
1
Yoga

Je ne suis pas tout à fait sûr de ce dont vous parlez, alors je mentionnerai les possibilités qui me viennent à l’esprit.

Peut être ça...

// Keep track of the last query for debug..
$this->last_query = $query;

http://core.trac.wordpress.org/browser/tags/3.5.2/wp-includes/wp-db.php#L1195

... est ce que vous parlez. Si tel est le cas, votre code exécute simplement la méthode flush qui réinitialise les propriétés $wpdb à null ou à des valeurs vides. Cela n'empêche rien et ne ressemble pas vraiment à la "mise en cache" non plus. Cela ajoute juste un peu plus de travail pour que PHP le fasse.

Ou peut-être parlez-vous de ceci:

$this->result = @mysql_query( $query, $this->dbh );

http://core.trac.wordpress.org/browser/tags/3.5.2/wp-includes/wp-db.php#L1200

Mais je ne sais pas comment cela compte comme "cache". La classe doit récupérer les résultats et les placer quelque part . Ce quelque part est $this->results;

Ou peut-être parlez-vous de ceci:

La fonction get_var renvoie une seule variable de la base de données. Bien qu'une seule variable soit renvoyée, l'intégralité du résultat de la requête est mis en cache pour une utilisation ultérieure. Retourne NULL si aucun résultat n'est trouvé.

http://codex.wordpress.org/Class_Reference/wpdb#SELECT_a_Variable

Si vous avez essayé $wpdb->get_var("SELECT ID FROM {$wpdb->posts}");, vous obtiendrez un ensemble de résultats égal aux lignes de votre base de données, mais get_var ne renverra qu'un résultat. Les autres résultats sont toujours conservés dans l'objet. Si vous avez besoin (légèrement) de ces résultats plus tard, ils sont disponibles sans autre requête.

var_dump($wpdb->get_var("SELECT ID FROM {$wpdb->posts}"));
var_dump($wpdb->last_result);

C’est la seule chose qui compte vraiment comme "mise en cache" dans mon esprit, bien que je n’en ai jamais eu besoin. Cela ne fait aucune différence avec votre requête, car celle-ci ne renverra de toute façon qu'une seule ligne.


Existe-t-il un meilleur moyen d'écrire la fonction ci-dessus?

Laissez $wpdb->flush() car je ne vois vraiment pas les avantages, dans aucun des cas mentionnés, en particulier avec une requête telle que "SELECT NOW()". Dès que la requête suivante sera exécutée, $wpdb->flush sera exécuté de toute façon.

Et il n'y a aucune raison de définir la variable $now puis return. Sauf si vous avez l'intention d'ajouter des contrôles de cohérence sur les données $now avant la modification de return, cochez return directement à partir de la requête.

Pourquoi $ wpdb met-il UNIQUEMENT en cache le dernier résultat mais pas toutes les requêtes dans la même requête? Cela semble un peu exagéré pour la dernière requête, non?

Malgré l'utilisation par le Codex du terme "cache", je ne suis pas sûr que la plupart de ces informations soient considérées comme un "cache", mais je ne discuterai pas de l'argument. C'est un cache très minimal s'il en est un. Le "cache" est principalement un artefact de la façon dont fonctionne $wpdb.

En ce qui concerne la "mise en cache" de chaque requête dans une requête, je m'attendrais à des problèmes de mémoire si vous essayiez cela - au moins avec certains serveurs. Imaginez 4 ou 5 très grands ensembles de résultats utilisant tous de la mémoire.

$wpdb n'est en réalité qu'une interface relativement simple à la base de données. C'est pratique, mais je suppose que vous le traitez peut-être comme si vous vous attendiez à ce qu'il soit plus que ce qu'il est. Il exécute une requête, enregistre un peu d'informations pour son usage personnel et pour le débogage. Lorsqu'une autre requête est exécutée, outre les informations de connexion de base et d'autres éléments de base tels que les raccourcis de nom de table ($wpdb->posts), elle est effacée et démarre. plus de. Ce n'est pas un gestionnaire de requêtes global ou un cache de requêtes.

Sur la base de la description mise à jour, j'ai exécuté:

function getNow() {
    global $wpdb;
    $now = $wpdb->get_var("SELECT NOW()");
    $wpdb->flush();
    return $now;
}

echo '<pre>';
echo getNow();
echo "\n";
sleep(10);
echo getNow(); // Same result as above
echo '</pre>';
die;

Et j'ai:

2013-06-25 10:37:06
2013-06-25 10:37:16

Chaque fois que je lance que les deux résultats diffèrent de dix secondes.

Ensuite, j'ai essayé avec la $wpdb->flush(); commentée. Même résultat. Cela a du sens, car $wpdb->flush(); est exécuté avant chaque requête comme vous pouvez le voir à partir de la source .

L'effet que vous voyez n'est pas le résultat du fonctionnement interne de $wpdb. Il existe un autre mécanisme de mise en cache en jeu.

1
s_ha_dum