PHP Australia Conference 2015

Mesure de l'efficacité du cache

PECL/mysqlnd_qc fournit 3 façons de mesurer l'efficacité du cache. La fonction mysqlnd_qc_get_normalized_query_trace_log() retourne des statistiques aggrégées par la normalisation d'une chaîne de requête, la fonction mysqlnd_qc_get_cache_info() fournit des informations spécifiques au gestionnaire de stockage qui incluent une liste de tous les éléments mis en cache, suivant le gestionnaire de stockage. De plus, le cooeur de PECL/mysqlnd_qc collecte un résumé haut niveau des statistiques aggrégées par processus PHP. Les statistiques haut niveau sont retournées par la fonction mysqlnd_qc_get_core_stats().

Les fonctions mysqlnd_qc_get_normalized_query_trace_log() et mysqlnd_qc_get_core_stats() ne collecteront pas de données tant que leurs directives de configuration PHP correspondantes ne sont pas activées. Veuillez vous reporter aux différents exemples pour récupérer les noms de ces directives de configuration. La collecte de données est désactivée par défaut et ce, en raison des impacts sur la performances. Elle est configurable via la directive de configuration mysqlnd_qc.time_statistics. La collecte de statistiques quant au durée est activée par défaut mais uniquement effectuée si la collecte de données a été activée. Le fait d'enregistrer des statistiques quant au durée cause beaucoup d'appels système. Dans la plupart des cas, le bénéfice d'une surveillance l'emporte sur la perte de performance dûe aux appels système additionnelles.

Exemple #1 Collecte de données statistiques avec la configuration ini mysqlnd_qc.time_statistics

mysqlnd_qc.enable_qc=1
mysqlnd_qc.collect_statistics=1
<?php
/* connexion à MySQL */
$mysqli = new mysqli("host""user""password""schema""port""socket");
$mysqli->query("DROP TABLE IF EXISTS test");
$mysqli->query("CREATE TABLE test(id INT)");
$mysqli->query("INSERT INTO test(id) VALUES (1), (2), (3)");

/* quelques requêtes */
for ($i 1$i <= 4$i++) {
  
$query sprintf("/*%s*/SELECT id FROM test WHERE id = %d",
     
MYSQLND_QC_ENABLE_SWITCH,
     
$i 2);
  
$res $mysqli->query($query);
  
$res->free();
}

var_dump(mysqlnd_qc_get_core_stats());
?>

Les exemples ci-dessus vont afficher :

array(26) {
  ["cache_hit"]=>
  string(1) "2"
  ["cache_miss"]=>
  string(1) "2"
  ["cache_put"]=>
  string(1) "2"
  ["query_should_cache"]=>
  string(1) "4"
  ["query_should_not_cache"]=>
  string(1) "3"
  ["query_not_cached"]=>
  string(1) "3"
  ["query_could_cache"]=>
  string(1) "4"
  ["query_found_in_cache"]=>
  string(1) "2"
  ["query_uncached_other"]=>
  string(1) "0"
  ["query_uncached_no_table"]=>
  string(1) "0"
  ["query_uncached_no_result"]=>
  string(1) "0"
  ["query_uncached_use_result"]=>
  string(1) "0"
  ["query_aggr_run_time_cache_hit"]=>
  string(2) "28"
  ["query_aggr_run_time_cache_put"]=>
  string(3) "900"
  ["query_aggr_run_time_total"]=>
  string(3) "928"
  ["query_aggr_store_time_cache_hit"]=>
  string(2) "14"
  ["query_aggr_store_time_cache_put"]=>
  string(2) "40"
  ["query_aggr_store_time_total"]=>
  string(2) "54"
  ["receive_bytes_recorded"]=>
  string(3) "136"
  ["receive_bytes_replayed"]=>
  string(3) "136"
  ["send_bytes_recorded"]=>
  string(2) "84"
  ["send_bytes_replayed"]=>
  string(2) "84"
  ["slam_stale_refresh"]=>
  string(1) "0"
  ["slam_stale_hit"]=>
  string(1) "0"
  ["request_counter"]=>
  int(1)
  ["process_hash"]=>
  int(1929695233)
}

Pour une vue rapide, appelez la fonction mysqlnd_qc_get_core_stats(). Elle délivre l'utilisation du cache, les durées du cache, ainsi que les statistiques relatives au trafic. Les valeurs sont aggrégées pour chaque processus pour toutes les requêtes émises par n'importe quel appel API à PHP MySQL.

Quelques gestionnaires de stockage, comme le gestionnaire par défaut, peuvent signaler les entrées du cache, les statistiques relatives aux entrées et aux méta-données pour la requête sous-jacente via la fonction mysqlnd_qc_get_cache_info(). Notez que les informations retournées dépendant du gestionnaire de stockage. Les valeurs sont aggrégées pour chaque processus.

Exemple #2 Exemple avec mysqlnd_qc_get_cache_info()

mysqlnd_qc.enable_qc=1
<?php
/* connexion à MySQL */
$mysqli = new mysqli("host""user""password""schema""port""socket");
$mysqli->query("DROP TABLE IF EXISTS test");
$mysqli->query("CREATE TABLE test(id INT)");
$mysqli->query("INSERT INTO test(id) VALUES (1), (2), (3)");

/* quelques requêtes pour remplir les traces */
for ($i 1$i <= 4$i++) {
  
$query sprintf("/*%s*/SELECT id FROM test WHERE id = %d",
     
MYSQLND_QC_ENABLE_SWITCH,
     
$i 2);
  
$res $mysqli->query($query);
  
$res->free();
}
var_dump(mysqlnd_qc_get_cache_info());
?>

Les exemples ci-dessus vont afficher :

array(4) {
  ["num_entries"]=>
  int(2)
  ["handler"]=>
  string(7) "default"
  ["handler_version"]=>
  string(5) "1.0.0"
  ["data"]=>
  array(2) {
    ["Localhost via UNIX socket
3306
root
test|/*qc=on*/SELECT id FROM test WHERE id = 1"]=>
    array(2) {
      ["statistics"]=>
      array(11) {
        ["rows"]=>
        int(1)
        ["stored_size"]=>
        int(71)
        ["cache_hits"]=>
        int(1)
        ["run_time"]=>
        int(391)
        ["store_time"]=>
        int(27)
        ["min_run_time"]=>
        int(16)
        ["max_run_time"]=>
        int(16)
        ["min_store_time"]=>
        int(8)
        ["max_store_time"]=>
        int(8)
        ["avg_run_time"]=>
        int(8)
        ["avg_store_time"]=>
        int(4)
      }
      ["metadata"]=>
      array(1) {
        [0]=>
        array(8) {
          ["name"]=>
          string(2) "id"
          ["orig_name"]=>
          string(2) "id"
          ["table"]=>
          string(4) "test"
          ["orig_table"]=>
          string(4) "test"
          ["db"]=>
          string(4) "test"
          ["max_length"]=>
          int(1)
          ["length"]=>
          int(11)
          ["type"]=>
          int(3)
        }
      }
    }
    ["Localhost via UNIX socket
3306
root
test|/*qc=on*/SELECT id FROM test WHERE id = 0"]=>
    array(2) {
      ["statistics"]=>
      array(11) {
        ["rows"]=>
        int(0)
        ["stored_size"]=>
        int(65)
        ["cache_hits"]=>
        int(1)
        ["run_time"]=>
        int(299)
        ["store_time"]=>
        int(13)
        ["min_run_time"]=>
        int(11)
        ["max_run_time"]=>
        int(11)
        ["min_store_time"]=>
        int(6)
        ["max_store_time"]=>
        int(6)
        ["avg_run_time"]=>
        int(5)
        ["avg_store_time"]=>
        int(3)
      }
      ["metadata"]=>
      array(1) {
        [0]=>
        array(8) {
          ["name"]=>
          string(2) "id"
          ["orig_name"]=>
          string(2) "id"
          ["table"]=>
          string(4) "test"
          ["orig_table"]=>
          string(4) "test"
          ["db"]=>
          string(4) "test"
          ["max_length"]=>
          int(0)
          ["length"]=>
          int(11)
          ["type"]=>
          int(3)
        }
      }
    }
  }
}

Il est possible de décomposer davantage le niveau de granularité des statistiques au niveau de la chaîne de requête normalisée. La chaîne de requête normalisée correspond à la chaîne de requête avec tous les paramètres remplacés avec les marqueurs. Par exemple, les deux requêtes SELECT id FROM test WHERE id = 0 et SELECT id FROM test WHERE id = 1 sont normalisées en SELECT id FROM test WHERE id = ?. Les statistiques pour ces deux requêtes sont aggrégées en une seule entrée pour SELECT id FROM test WHERE id = ?.

Exemple #3 Exemple avec mysqlnd_qc_get_normalized_query_trace_log()

mysqlnd_qc.enable_qc=1
mysqlnd_qc.collect_normalized_query_trace=1
<?php
/* connexion à MySQL */
$mysqli = new mysqli("host""user""password""schema""port""socket");
$mysqli->query("DROP TABLE IF EXISTS test");
$mysqli->query("CREATE TABLE test(id INT)");
$mysqli->query("INSERT INTO test(id) VALUES (1), (2), (3)");

/* quelques requêtes pour remplir les traces */
for ($i 1$i <= 4$i++) {
  
$query sprintf("/*%s*/SELECT id FROM test WHERE id = %d",
     
MYSQLND_QC_ENABLE_SWITCH,
     
$i 2);
  
$res $mysqli->query($query);
  
$res->free();
}
var_dump(mysqlnd_qc_get_normalized_query_trace_log());
?>

Les exemples ci-dessus vont afficher :

array(4) {
  [0]=>
  array(9) {
    ["query"]=>
    string(25) "DROP TABLE IF EXISTS test"
    ["occurences"]=>
    int(0)
    ["eligible_for_caching"]=>
    bool(false)
    ["avg_run_time"]=>
    int(0)
    ["min_run_time"]=>
    int(0)
    ["max_run_time"]=>
    int(0)
    ["avg_store_time"]=>
    int(0)
    ["min_store_time"]=>
    int(0)
    ["max_store_time"]=>
    int(0)
  }
  [1]=>
  array(9) {
    ["query"]=>
    string(27) "CREATE TABLE test (id INT )"
    ["occurences"]=>
    int(0)
    ["eligible_for_caching"]=>
    bool(false)
    ["avg_run_time"]=>
    int(0)
    ["min_run_time"]=>
    int(0)
    ["max_run_time"]=>
    int(0)
    ["avg_store_time"]=>
    int(0)
    ["min_store_time"]=>
    int(0)
    ["max_store_time"]=>
    int(0)
  }
  [2]=>
  array(9) {
    ["query"]=>
    string(46) "INSERT INTO test (id ) VALUES (? ), (? ), (? )"
    ["occurences"]=>
    int(0)
    ["eligible_for_caching"]=>
    bool(false)
    ["avg_run_time"]=>
    int(0)
    ["min_run_time"]=>
    int(0)
    ["max_run_time"]=>
    int(0)
    ["avg_store_time"]=>
    int(0)
    ["min_store_time"]=>
    int(0)
    ["max_store_time"]=>
    int(0)
  }
  [3]=>
  array(9) {
    ["query"]=>
    string(31) "SELECT id FROM test WHERE id =?"
    ["occurences"]=>
    int(4)
    ["eligible_for_caching"]=>
    bool(true)
    ["avg_run_time"]=>
    int(179)
    ["min_run_time"]=>
    int(11)
    ["max_run_time"]=>
    int(393)
    ["avg_store_time"]=>
    int(12)
    ["min_store_time"]=>
    int(7)
    ["max_store_time"]=>
    int(25)
  }
}

Les sources de la distribution de PECL/mysqlnd_qc contiennent un dossier web/ dans lequel se trouve un script fournissant un exemple de surveillance du cache. Veuillez suivre les instructions se trouvant dans cette source.

Depuis PECL/mysqlnd_qc 1.1.0, il est possible d'écrire les statistiques dans un fichier de log. Voir la directive de configuration log file. Please, see mysqlnd_qc.collect_statistics_log_file pour plus d'informations.

add a note add a note

User Contributed Notes

There are no user contributed notes for this page.
To Top