2013-07-20 8 views
3

J'ai une base de données mysql avec beaucoup de tables. Cette base de données alimente un site web qui reçoit de plus en plus de trafic.Mesurer la 'charge' de MySQL à partir de l'utilisation de la requête et de la fréquence du type de requête

J'ai conçu ma base de données et mes requêtes pour éviter intentionnellement les jointures qui créeraient des goulots d'étranglement au niveau des performances, et ainsi je pourrais diviser mes tables sur des serveurs séparés si nécessaire. peut partitionner des tables individuelles au besoin). Ma question est la suivante: étant donné le nombre de tables que je possède, existe-t-il un moyen facile de détecter quelle table et quelles requêtes reçoivent le plus de «charge»? Je me pose des questions sur les tables à lecture/écriture élevée.

Je veux un moyen de dire (en dehors de regarder mon code et les journaux) pour déterminer quelles tables doivent être déplacées vers d'autres serveurs pour distribuer les demandes et gérer les ressources. J'utilise le terme «charge» généralement je sais, et peut-être incorrectement (?).

Merci!

Répondre

3

C'est précisément ce que la boîte à outils Percona a été fait pour (parmi beaucoup d'autres choses). Plus précisément, pt-query-digest (Link) - vous pouvez l'utiliser pour un grand nombre d'utilitaires, des requêtes lentes à la détection d'injection SQL.

Dans ce cas pt-query-digest peut être utilisé avec la stratégie générale de la configuration de votre long_query_time pour enregistrer toutes les requêtes dans le fichier slow_query_log en définissant la long_query_time = 0. Maintenant, toutes les requêtes sont enregistrées dans le fichier de requête lente (assurez-vous réinitialiser l'heure à la valeur précédente).

mysql> SELECT @@GLOBAL.slow_query_log_file; 
+------------------------------------------+ 
| @@GLOBAL.slow_query_log_file    | 
+------------------------------------------+ 
| /var/lib/ubuntu/mysql/slowquery.log   | 
+------------------------------------------+ 
1 row in set (0.00 sec) 
mysql> SET GLOBAL slow_query_log_file='/tmp/sniffed_queries.log'; 
mysql> SET GLOBAL long_query_time = 0; 
mysql> FLUSH LOGS; #Clear the logs 

Alors maintenant, vous avez un journal à portée de main de toutes les requêtes exécutées sur votre serveur, sans déconner avec votre journal général ou d'une autre table, pour analyser avec pt-query-digest:

pt-query-digest /tmp/sniffed_queries.log 

Produira une grande sortie qui est extrêment utile, d'intérêt pour vous pour commencer:

# Profile 
# Rank Query ID   Response time Calls R/Call Apdx V/M Item 
# ==== ================== ============= ===== ====== ==== ===== ========== 
# 1 0x92F3B1B361FB0E5B 4.0522 50.0% 312 0.0130 1.00 0.00 SELECT wp_options 
# 2 0xE71D28F50D128F0F 0.8312 10.3% 6412 0.0001 1.00 0.00 SELECT poller_output poller_item 
# 3 0x211901BF2E1C351E 0.6811 8.4% 6416 0.0001 1.00 0.00 SELECT poller_time 
# 4 0xA766EE8F7AB39063 0.2805 3.5% 149 0.0019 1.00 0.00 SELECT wp_terms wp_term_taxonomy wp_term_relationships 
# 5 0xA3EEB63EFBA42E9B 0.1999 2.5% 51 0.0039 1.00 0.00 SELECT UNION wp_pp_daily_summary wp_pp_hourly_summary wp_pp_hits wp_posts 
# 6 0x94350EA2AB8AAC34 0.1956 2.4% 89 0.0022 1.00 0.01 UPDATE wp_options 
# 7 0x7AEDF19FDD3A33F1 0.1381 1.7% 909 0.0002 1.00 0.00 SELECT wp_options 
# 8 0x4C16888631FD8EDB 0.1160 1.4%  5 0.0232 1.00 0.00 SELECT film 
# 9 0xCFC0642B5BBD9AC7 0.0987 1.2% 50 0.0020 1.00 0.01 SELECT UNION wp_pp_daily_summary wp_pp_hourly_summary wp_pp_hits 
# 10 0x88BA308B9C0EB583 0.0905 1.1%  4 0.0226 1.00 0.01 SELECT poller_item 
# 11 0xD0A520C9DB2D6AC7 0.0850 1.0% 125 0.0007 1.00 0.00 SELECT wp_links wp_term_relationships wp_term_taxonomy 
# 12 0x30DA85C940E0D491 0.0835 1.0% 542 0.0002 1.00 0.00 SELECT wp_posts 
# 13 0x8A52FE35D340A347 0.0767 0.9%  4 0.0192 1.00 0.00 TRUNCATE TABLE poller_time 
# 14 0x3E84BF7C0C2A3005 0.0624 0.8% 272 0.0002 1.00 0.00 SELECT wp_postmeta 
# 15 0xA01053DA94ED829E 0.0567 0.7% 213 0.0003 1.00 0.00 SELECT data_template_rrd data_input_fields 
# 16 0xBE797E1DD5E4222F 0.0524 0.6% 79 0.0007 1.00 0.00 SELECT wp_posts 
# 17 0xF8EC4434E0061E89 0.0475 0.6% 62 0.0008 1.00 0.00 SELECT wp_terms wp_term_taxonomy 
# 18 0xCDFFAD848B0C1D52 0.0465 0.6%  9 0.0052 1.00 0.01 SELECT wp_posts wp_term_relationships 
# 19 0x5DE709416871BF99 0.0454 0.6% 260 0.0002 1.00 0.00 DELETE poller_output 
# 20 0x428A588445FE580B 0.0449 0.6% 260 0.0002 1.00 0.00 INSERT poller_output 
# MISC 0xMISC    0.8137 10.0% 3853 0.0002 NS 0.0 
<147 ITEMS> 

partir de cet exemple on peut voir que le système R/Appel à la SELECT ... FROM appel wp_options provoque la plus grande charge. Il y a une tonne de super autres infos. Je vous recommande vivement d'utiliser la boîte à outils percona tôt et souvent si vous voulez rester avec mysql - je les ai mis loin, trop longtemps et je me bats encore pour les maux de tête qu'ils auraient empêchés.

Percona a un grand article sur ce sujet, il est pour leur construire MySQL Percona Server, ce qui est excellent, mais doit encore appliquer: Identifying the load with the help of pt-query-digest and Percona Server

+0

Je ne l'ai pas encore essayé votre solution, mais je regardais en elle et semble vouloir faire ce que je veux. Réponse acceptée – Tucker

+0

Wow! On dirait que c'est le meilleur outil de profil que j'ai jamais vu et votre réponse détaillée sur la façon de l'utiliser est parfaite! Tu fais ma journée! Merci! – user3479125

0

Vous pouvez définir des déclencheurs sur la table et faire en sorte que le déclencheur insère le nom de la table qui doit être utilisé dans une table de suivi distincte.

Je pourrais voir deux façons de mettre en place un tel déclencheur.

1. Faites insérer la gâchette dans la table de suivi à chaque fois. Votre table de suivi stocke le nom de la table à opérer. Vous pouvez ensuite comptabiliser le nombre de mises à jour en regroupant la table de suivi par nom de table. Le problème ici serait que chaque mise à jour nécessiterait une ligne séparée.

  1. Demandez à la table de suivi de stocker à la fois le nom et le nombre de tables. Ensuite, demandez au déclencheur de mettre à jour le compte si nécessaire:
    par ex.
    SELECT * FROM trackTable WHERE nom_table = 'nom_seule';
    IF @@ ROWCOUNT == 0 - quelquechose de nom n'est pas déjà dans la table de suivi
    BEGIN
    INSERT INTO sometablename VALEURS ('sometablename, 1); - Insérer dans la table, compte = 1
    FIN
    SINON
    BEGIN
    DÉCLARER @count AS INT;
    SET @count = (CHOISIR le compte FROM trackingTable WHERE nom_table = 'quelquechose');
    SET @count = @ compte + 1; - Incrémenter le comptage de 1
    UPDATE trackingTable SET theCount = @ count WHERE nom_table = 'nomSetable';
    FIN