web-dev-qa-db-fra.com

Pour une requête MySQL, comment déterminez-vous les E / S physiques et logiques?

Je suis habitué à avoir un showplan dans Microsoft SQL et je suis devenu paresseux d'utiliser des outils pour syntoniser les requêtes MySQL. Comment puis-je déterminer les E/S physiques/logiques pour une requête dans MySQL? (Expliquer montre la sélection de l'index, mais je souhaite plus d'informations à partir du serveur MySQL, si possible).

7
David Hall

Je recommande d'utiliser Percona Server pour les améliorations des journaux de requête lente. J'ai répondu à un fil similaire à ce sujet sur la pile débordement:

https://stackoverflow.com/questions/3393206/what-is-the-equivalent-query-in-mysql/3443944#3443944

Jetez un coup d'œil à cela en particulier (à partir de - http://www.percona.com/docs/wiki/percona-server:Features:SLOW_EXTENDIDEZEDIRECT=1#CANGES_TO_THE_LOG_FORMAT ):

# User@Host: mailboxer[mailboxer] @  [192.168.10.165]
# Thread_id: 11167745  Schema: board
# QC_Hit: No  Full_scan: No  Full_join: No  Tmp_table: Yes  Disk_tmp_table: No
# Filesort: Yes  Disk_filesort: No  Merge_passes: 0
# Query_time: 0.000659  Lock_time: 0.000070  Rows_sent: 0  Rows_examined: 30  Rows_affected: 0  Rows_read: 30
#   InnoDB_IO_r_ops: 1  InnoDB_IO_r_bytes: 16384  InnoDB_IO_r_wait: 0.028487
#   InnoDB_rec_lock_wait: 0.000000  InnoDB_queue_wait: 0.000000
#   InnoDB_pages_distinct: 5
select count(distinct author_id) from art87.article87 force index (forum_id) where forum_id = 240215 and thread_id = '710575' 
6
Morgan Tocker

Vous pouvez estimer les performances de la requête en examinant le nombre de recherches sur disque.

Le Optimisation Portion du manuel MySQL explique l'un des moyens les plus utiles d'estimation des exigences d'E/S et de réglage ultérieures. Explorer le nombre de lectures et estimation Quincaillerie IO Devrait vous donner une indication assez claire des exigences d'accès au disque. De plus, en ajustant les tailles de tampon, vous pourrez voir l'implication de la mémoire et la mise en cache sur votre requête.

4

Ce n'est pas parfait, mais vous devriez pouvoir faire

mysql> show variables where variable_name like '%innodb%';

Pour le nombre de lectures physiques, regardez le Innodb_buffer_pool_reads Counter, et pour des lectures logiques, regardez Innodb_buffer_pool_read_requests. Pour être utile, vous devez prendre une note de ces numéros, puis exécuter une charge de travail représentative, puis diviser le nombre de lectures logiques pour rechercher des lectures logiques par requête. Si vous avez de la chance, le nombre de lectures physiques augmentera vers le début de votre test de test, puis rester constant.

3
Gaius

Avec quelques travaux, vous pouvez voir combien de "travail" votre requête prend votre requête.

mysql> FLUSH STATUS;           -- In newer MySQLs, this clears the "SESSION" values
Query OK, 0 rows affected (0.00 sec)    

mysql> SHOW SESSION STATUS LIKE 'Handler%';
+----------------------------+-------+
| Variable_name              | Value |
+----------------------------+-------+
| Handler_commit             | 0     |
| Handler_delete             | 0     |
| Handler_discover           | 0     |
| Handler_prepare            | 0     |
| Handler_read_first         | 0     |
| Handler_read_key           | 0     |
| Handler_read_next          | 0     |
| Handler_read_prev          | 0     |
| Handler_read_rnd           | 0     |
| Handler_read_rnd_next      | 0     |
| Handler_rollback           | 0     |
| Handler_savepoint          | 0     |
| Handler_savepoint_rollback | 0     |
| Handler_update             | 0     |
| Handler_write              | 0     |
+----------------------------+-------+
15 rows in set (0.00 sec)

mysql> SELECT * FROM ts;
+----+---------------------+
| id | ts                  |
+----+---------------------+
|  1 | 2011-03-24 20:47:38 |
|  2 | 2011-03-24 20:46:29 |
|  3 | 2011-03-24 20:46:43 |
+----+---------------------+
3 rows in set (0.00 sec)

mysql> SHOW SESSION STATUS LIKE 'Handler%';
+----------------------------+-------+
| Variable_name              | Value |
+----------------------------+-------+
| Handler_commit             | 1     |
| Handler_delete             | 0     |
| Handler_discover           | 0     |
| Handler_prepare            | 0     |
| Handler_read_first         | 1     |
| Handler_read_key           | 2     |
| Handler_read_next          | 0     |
| Handler_read_prev          | 0     |
| Handler_read_rnd           | 0     |
| Handler_read_rnd_next      | 4     |  <-- 3 rows, plus 1 to realize it is finished
| Handler_rollback           | 0     |
| Handler_savepoint          | 0     |
| Handler_savepoint_rollback | 0     |
| Handler_update             | 0     |
| Handler_write              | 0     |
+----------------------------+-------+
15 rows in set (0.00 sec)

mysql> SHOW STATUS LIKE 'Up%';
+---------------------------+---------+
| Variable_name             | Value   |
+---------------------------+---------+
| Uptime                    | 3287334 |
| Uptime_since_flush_status | 68      |
+---------------------------+---------+
2 rows in set (0.00 sec)

Eh bien, cela ne vous donne pas les réponses non mises en cache vs non mises en cache, mais cela vous donne des indices intéressants.

Hélas, les statuts Innodb sont mondiaux. Donc, vous devez les capturer avant et après. Pire encore, d'autres requêtes vont aussi cogner les valeurs.

mysql> SHOW SESSION STATUS LIKE 'Innodb_buffer_pool%';
+---------------------------------------+-------------+
| Variable_name                         | Value       |
+---------------------------------------+-------------+
| Innodb_buffer_pool_pages_data         | 279861      |
| Innodb_buffer_pool_pages_dirty        | 52          |
| Innodb_buffer_pool_pages_flushed      | 15992658    |
| Innodb_buffer_pool_pages_free         | 96          |
| Innodb_buffer_pool_pages_misc         | 8043        |
| Innodb_buffer_pool_pages_total        | 288000      |
| Innodb_buffer_pool_read_ahead         | 2567477     |
| Innodb_buffer_pool_read_ahead_evicted | 262237      |
| Innodb_buffer_pool_read_requests      | 26565709230 |
| Innodb_buffer_pool_reads              | 1339717     |
| Innodb_buffer_pool_wait_free          | 0           |
| Innodb_buffer_pool_write_requests     | 865548882   |
+---------------------------------------+-------------+
12 rows in set (0.00 sec)

mysql> SELECT * FROM ts;
+----+---------------------+
| id | ts                  |
+----+---------------------+
|  1 | 2011-03-24 20:47:38 |
|  2 | 2011-03-24 20:46:29 |
|  3 | 2011-03-24 20:46:43 |
+----+---------------------+
3 rows in set (0.00 sec)

mysql> SHOW STATUS LIKE 'Innodb_buffer_pool%';
+---------------------------------------+-------------+
| Variable_name                         | Value       |
+---------------------------------------+-------------+
| Innodb_buffer_pool_pages_data         | 279865      |
| Innodb_buffer_pool_pages_dirty        | 8           |
| Innodb_buffer_pool_pages_flushed      | 15992842    |
| Innodb_buffer_pool_pages_free         | 92          |
| Innodb_buffer_pool_pages_misc         | 8043        |
| Innodb_buffer_pool_pages_total        | 288000      |
| Innodb_buffer_pool_read_ahead         | 2567477     |
| Innodb_buffer_pool_read_ahead_evicted | 262237      |
| Innodb_buffer_pool_read_requests      | 26565712655 |  <-- This went up
| Innodb_buffer_pool_reads              | 1339717     |  <-- No chg = no disk reads
| Innodb_buffer_pool_wait_free          | 0           |
| Innodb_buffer_pool_write_requests     | 865550805   |
+---------------------------------------+-------------+
12 rows in set (0.00 sec)

Mon mantra "comptez les haits de disque".

1
Rick James