Gibt es ein Tool wie den „SQL Server Profiler“ von Microsoft für MySQL? [geschlossen]


43

Während der Entwicklung auf MySQL vermisse ich es wirklich, einen Profiler starten zu können. Ich finde, SQLyog ist ein guter Ersatz für Query Analyzer, aber ich habe kein Tool gefunden, das wie SQL Profiler funktioniert.

Für die MySQL-Leute, die den SQL Profiler von Microsoft noch nicht gesehen haben , ist hier ein Screenshot

profiler sql

Bei meinem vorherigen Job hatten wir ein Tool, das SQL Profiler übertrumpfte und uns sogar Stack-Traces gab

altiris profiler

Kennt jemand irgendwelche Tools wie die, die ich erwähnt habe, die mit MySQL funktionieren?

(Zu Ihrer Information, ich kann Altiris Profiler für die Arbeit mit MySQL einsetzen, aber es wird weiterhin Windows erfordern, da es sich nicht wirklich um eine Symantec-Lizenz handelt, ist die Lizenzierung sehr schwierig.)

Antworten:


17

MySQL hat noch nie ein Abfrageprofil erstellt. Jetzt, da MySQL von Oracle großgeschrieben wird, weiß ich, dass dies auch weiterhin der Fall sein wird.

Dennoch ist nicht alle Hoffnung verloren.

Seit 2007 hat Percona einige absolut hervorragende Tools für alles, was ein Entwickler und DBA sich wünscht, entwickelt, einschließlich der Abfrageprofilerstellung.

Perconas erstes Tool-Set, MAATKIT , wurde für den ernsthaften Benutzer von MySQL entwickelt. Es verfügt über viele Dinge , wie zum Beispiel:

  • Abfrageprofilerstellung
  • Replikations-Heartbeat
  • Replikations-Slave-Verwaltung
  • Tabellenprüfsumme und Synchronisation

Percona hat MAATKIT kürzlich zu einem aktuelleren Werkzeugsatz gemacht, der heute als Percona Toolkit bekannt ist . Diese Tools haben an der Stelle, an der MAATKIT aufgehört hat, das Tätigkeitsfeld für den seriösen MySQL-Benutzer um folgende Funktionen erweitert:

  • Fremdschlüssel-Fehlerprüfung
  • Online-Schemaänderung
  • Visuelle Erklärungspläne
  • und mehr ...

Zurück zur ursprünglichen Frage: Die Tools für die Abfrageprofilerstellung sind

Im Folgenden finden Sie ein Beispiel für eine Vielzahl von Informationen, die mit einem dieser Tools bereitgestellt werden können:

Ich half einem Client bei der Implementierung von mk-query-digest, um alle 20 Minuten die 20 Anfragen mit der schlechtesten Leistung zu melden. Ich habe die Idee von diesem YouTube-Video . Der Client verschiebt die Ausgabe einer fehlerhaften Abfrage in den Speicher, wodurch die Häufigkeit verringert wird, mit der die Abfrage die Datenbank in Mitleidenschaft zieht.

Hier ist das Skript, das ich erstellt habe, um mk-query-digest aufzurufen (nur die Prozessliste überprüfend)

#!/bin/sh

RUNFILE=/tmp/QueriesAreBeingDigested.txt
if [ -f ${RUNFILE} ] ; then exit ; fi

MKDQ=/usr/local/sbin/mk-query-digest
RUNTIME=${1}
COPIES_TO_KEEP=${2}
DBVIP=${3}

WHICH=/usr/bin/which
DATE=`${WHICH} date`
ECHO=`${WHICH} echo`
HEAD=`${WHICH} head`
TAIL=`${WHICH} tail`
AWK=`${WHICH} awk`
SED=`${WHICH} sed`
CAT=`${WHICH} cat`
WC=`${WHICH} wc`
RM=`${WHICH} rm | ${TAIL} -1 | ${AWK} '{print $1}'`
LS=`${WHICH} ls | ${TAIL} -1 | ${AWK} '{print $1}'`

HAS_THE_DBVIP=`/sbin/ip addr show | grep "scope global secondary" | grep -c "${DBVIP}"`
if [ ${HAS_THE_DBVIP} -eq 1 ] ; then exit ; fi

DT=`${DATE} +"%Y%m%d_%H%M%S"`
UNIQUETAG=`${ECHO} ${SSH_CLIENT}_${SSH_CONNECTION}_${DT} | ${SED} 's/\./ /g' | ${SED} 's/ //g'`

cd /root/QueryDigest
OUTFILE=QP_${DT}.txt
HOSTADDR=${DBVIP}
${MKDQ} --processlist h=${HOSTADDR},u=queryprofiler,p=queryprofiler --run-time=${RUNTIME} > ${OUTFILE}

#
# Rotate out Old Copies
#

QPFILES=QPFiles.txt
QPFILES2ZAP=QPFiles2Zap.txt
${LS} QP_[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]_[0-9][0-9][0-9][0-9][0-9][0-9].txt > ${QPFILES}

LINECOUNT=`${WC} -l < ${QPFILES}`
if [ ${LINECOUNT} -gt ${COPIES_TO_KEEP} ]
then
        (( DIFF = LINECOUNT - COPIES_TO_KEEP ))
        ${HEAD} -${DIFF} < ${QPFILES} > ${QPFILES2ZAP}
        for QPFILETOZAP in `${CAT} ${QPFILES2ZAP}`
        do
                ${RM} ${QPFILETOZAP}
        done
fi

rm -f ${QPFILES2ZAP}
rm -f ${QPFILES}
rm -f ${RUNFILE}

Hier ist der Benutzer, den ich gemacht habe, um mit mk-query-digest eine Verbindung zu MySQL herzustellen

GRANT PROCESS ON *.* TO 'queryprofiler'@'%' IDENTIFIED BY 'queryprofiler';

Hier ist die Crontab, die ich alle 20 Minuten (weniger als 10 Sekunden) ausgeführt habe, wobei die letzten 144 Kopien (dh 48 Stunden Profilerstellung) aufbewahrt wurden.

*/20 * * * * /root/QueryDigest/ExecQueryDigest.sh 1190s 144 10.1.1.8

Der unglaubliche Teil: Die Ausgabe von mk-query-digest

Hier ist ein Profil, das am 28.12.2011 11:20:00 für 1190 Sek. Lief (20 Min. Weniger als 10 Sek.)

Die letzten 22 Zeilen

# Rank Query ID           Response time    Calls   R/Call     Item
# ==== ================== ================ ======= ========== ====
#    1 0x5E994008E9543B29    40.3255 11.2%     101   0.399263 SELECT schedule_occurrence schedule_eventschedule schedule_event schedule_eventtype schedule_event schedule_eventtype schedule_occurrence.start
#    2 0x392F6DA628C7FEBD    33.9181  9.4%      17   1.995184 SELECT mt_entry mt_objecttag
#    3 0x6C6318E56E149036    26.4695  7.3%     102   0.259505 SELECT schedule_occurrence schedule_eventschedule schedule_event schedule_eventtype schedule_event schedule_eventtype schedule_occurrence.start
#    4 0x00F66961DAE6FFB2    25.5472  7.1%      55   0.464495 SELECT mt_entry mt_placement mt_category
#    5 0x99E13015BFF1E75E    22.3618  6.2%     199   0.112371 SELECT mt_entry mt_objecttag
#    6 0x84DD09F0FC444677    22.3516  6.2%      39   0.573118 SELECT mt_entry
#    7 0x440EBDBCEDB88725    21.1817  5.9%      36   0.588380 SELECT mt_entry
#    8 0x8D258C584B858811    17.2402  4.8%      37   0.465951 SELECT mt_entry mt_placement mt_category
#    9 0x4E2CB0F4CAFD1400    16.9768  4.7%      40   0.424419 SELECT mt_entry mt_placement mt_category
#   10 0x377E0D0898266FDD    16.6979  4.6%     150   0.111319 SELECT polls_pollquestion mt_category
#   11 0x3B9686D98BB8E054    16.2089  4.5%      32   0.506529 SELECT mt_entry mt_objecttag mt_tag
#   12 0x97F670B604A85608    15.6158  4.3%      34   0.459287 SELECT mt_entry mt_placement mt_category
#   13 0x3F5557DA231225EB    14.4309  4.0%      36   0.400859 SELECT mt_entry mt_placement mt_category
#   14 0x191D660A10738896    13.1220  3.6%      31   0.423290 SELECT mt_entry mt_placement mt_category
#   15 0xF88F7421DD88036D    12.1261  3.4%      61   0.198788 SELECT mt_entry mt_blog mt_objecttag mt_tag mt_author
#   16 0xA909BF76E7051792    10.3971  2.9%      53   0.196172 SELECT mt_entry mt_objecttag mt_tag
#   17 0x3D42D07A335ED983     9.1424  2.5%      20   0.457121 SELECT mt_entry mt_placement mt_category
#   18 0x59F43B57DD43F2BD     9.0533  2.5%      21   0.431111 SELECT mt_entry mt_placement mt_category
#   19 0x7961BD4C76277EB7     8.5564  2.4%      47   0.182052 INSERT UNION UPDATE UNION mt_session
#   20 0x173EB4903F3B6DAC     8.5394  2.4%      22   0.388153 SELECT mt_entry mt_placement mt_category

Beachten Sie, dass dies die Liste der 20 Abfragen mit der schlechtesten Leistung basierend auf der Antwortzeit der Abfrage geteilt durch die Anzahl der Aufrufe der Abfrage ist.

Wenn 0x5E994008E9543B29wir uns die Abfrage-ID Nr. 1 ansehen , finden wir diese Abfrage-ID in der Ausgabedatei. Hier ist der Bericht für diese bestimmte Abfrage:

# Query 1: 0.09 QPS, 0.03x concurrency, ID 0x5E994008E9543B29 at byte 0 __
# This item is included in the report because it matches --limit.
#              pct   total     min     max     avg     95%  stddev  median
# Count          4     101
# Exec time      7     40s   303ms      1s   399ms   992ms   198ms   293ms
# Lock time      0       0       0       0       0       0       0       0
# Users                  1      mt
# Hosts                101 10.64.95.73:33750 (1), 10.64.95.73:34452 (1), 10.64.95.73:38440 (1)... 97 more
# Databases              1     mt1
# Time range 1325089201 to 1325090385
# bytes          0 273.60k   2.71k   2.71k   2.71k   2.62k       0   2.62k
# id             4 765.11M   7.57M   7.58M   7.58M   7.29M    0.12   7.29M
# Query_time distribution
#   1us
#  10us
# 100us
#   1ms
#  10ms
# 100ms  ################################################################
#    1s  ######
#  10s+
# Tables
#    SHOW TABLE STATUS FROM `mt1` LIKE 'schedule_occurrence'\G
#    SHOW CREATE TABLE `mt1`.`schedule_occurrence`\G
#    SHOW TABLE STATUS FROM `mt1` LIKE 'schedule_eventschedule'\G
#    SHOW CREATE TABLE `mt1`.`schedule_eventschedule`\G
#    SHOW TABLE STATUS FROM `mt1` LIKE 'schedule_event'\G
#    SHOW CREATE TABLE `mt1`.`schedule_event`\G
#    SHOW TABLE STATUS FROM `mt1` LIKE 'schedule_eventtype'\G
#    SHOW CREATE TABLE `mt1`.`schedule_eventtype`\G
#    SHOW TABLE STATUS FROM `schedule_occurrence` LIKE 'start'\G
#    SHOW CREATE TABLE `schedule_occurrence`.`start`\G
# EXPLAIN
SELECT `schedule_occurrence`.`id`, `schedule_occurrence`.`schedule_id`, `schedule_occurrence`.`event_id`, `schedule_occurrence`.`start`, `schedule_occurrence`.`end`, `schedule_occurrence`.`cancelled`, `schedule_occurrence`.`original_start`, `schedule_occurrence`.`original_end`, `schedule_occurrence`.`all_day`, `schedule_occurrence`.`ongoing`, `schedule_occurrence`.`featured`, `schedule_eventschedule`.`id`, `schedule_eventschedule`.`event_id`, `schedule_eventschedule`.`start`, `schedule_eventschedule`.`end`, `schedule_eventschedule`.`all_day`, `schedule_eventschedule`.`ongoing`, `schedule_eventschedule`.`min_date_calculated`, `schedule_eventschedule`.`max_date_calculated`, `schedule_eventschedule`.`rule`, `schedule_eventschedule`.`end_recurring_period`, `schedule_eventschedule`.`textual_description`, `schedule_event`.`id`, `schedule_event`.`title`, `schedule_event`.`slug`, `schedule_event`.`description`, `schedule_event`.`host_id`, `schedule_event`.`cost`, `schedule_event`.`age_restrictions`, `schedule_event`.`more_info`, `schedule_event`.`photo_id`, `schedule_event`.`contact_email`, `schedule_event`.`event_type_id`, `schedule_event`.`featured`, `schedule_event`.`staff_pick`, `schedule_event`.`futuremost`, `schedule_event`.`creator_id`, `schedule_event`.`created_on`, `schedule_event`.`allow_comments`, `schedule_event`.`mt_entry`, `schedule_eventtype`.`id`, `schedule_eventtype`.`parent_id`, `schedule_eventtype`.`name`, `schedule_eventtype`.`slug`, `schedule_eventtype`.`lft`, `schedule_eventtype`.`rght`, `schedule_eventtype`.`tree_id`, `schedule_eventtype`.`level`, T5.`id`, T5.`title`, T5.`slug`, T5.`description`, T5.`host_id`, T5.`cost`, T5.`age_restrictions`, T5.`more_info`, T5.`photo_id`, T5.`contact_email`, T5.`event_type_id`, T5.`featured`, T5.`staff_pick`, T5.`futuremost`, T5.`creator_id`, T5.`created_on`, T5.`allow_comments`, T5.`mt_entry`, T6.`id`, T6.`parent_id`, T6.`name`, T6.`slug`, T6.`lft`, T6.`rght`, T6.`tree_id`, T6.`level` FROM `schedule_occurrence` INNER JOIN `schedule_eventschedule` ON (`schedule_occurrence`.`schedule_id` = `schedule_eventschedule`.`id`) INNER JOIN `schedule_event` ON (`schedule_eventschedule`.`event_id` = `schedule_event`.`id`) INNER JOIN `schedule_eventtype` ON (`schedule_event`.`event_type_id` = `schedule_eventtype`.`id`) INNER JOIN `schedule_event` T5 ON (`schedule_occurrence`.`event_id` = T5.`id`) INNER JOIN `schedule_eventtype` T6 ON (T5.`event_type_id` = T6.`id`) WHERE (EXTRACT(MONTH FROM `schedule_occurrence`.`start`) = 8 AND EXTRACT(DAY FROM `schedule_occurrence`.`start`) = 6 AND `schedule_occurrence`.`start` BETWEEN '2011-01-01 00:00:00' and '2011-12-31 23:59:59.99') ORDER BY `schedule_occurrence`.`ongoing` ASC, `schedule_occurrence`.`all_day` DESC, `schedule_occurrence`.`start` ASC\G

Obwohl das Histogramm textbasiert ist, liefert es ein genaues Bild der Gesamtleistung der Abfrage, manchmal über 1 Sekunde und meistens zwischen 0,01 und 0,1 Sekunden. Von hier aus können Sie mit der Leistungsoptimierung fortfahren, indem Sie die Abfrage umgestalten, die Abfrageergebnisse im Speicher ablegen, fehlende oder überdeckende Indizes hinzufügen usw.

FAZIT

IMHO Wenn Percona die Profiler-Tools jemals in einer Windows-GUI platzieren würde, könnte es leicht mit dem SQL Server-Profiler von Microsoft mithalten.

Verteidigungsreste !!!


IMHO JetProfiler sieht so aus, als ob Percona Tools grafisch kombiniert wäre. Jeder hat Nuancen übereinander. Linux-Benutzer und Kommandozeilenmitarbeiter wären mit Percona Tools oder MAATKIT zufrieden. Mit JetProfiler müssen Sie nicht länger als DB arbeiten und haben nicht nur den grafischen Vorteil eines MONyog für Windows.
RolandoMySQLDBA


5

Nein, es gibt kein solches Tool.


Einverstanden. Ich habe festgestellt, dass die meisten MySQL-Entwickler / -Administratoren nie viel Zeit mit Microsoft SQL Server verbracht haben und nicht wissen, wie unglaublich der MS-Stack für die Entwicklung ist. Jedes MySQL-Abfragetool, das ich gesehen habe, hängt von der Abfrage ab, aber mit SQL Server können Sie fast alles, was mit der Datenbank geschieht, in Echtzeit verfolgen. Es gibt nichts, was dem Detail von SQL Server Profiler nahe kommt, da MySQL es einfach nicht unterstützt.
parleer

4

Der MySQL Query Profiler in Kombination mit den GUI-MySQL-Tools ist wahrscheinlich so ähnlich wie das SQL Server Profiler-Tool


2
Autsch, da gibt es keine GUI ...
Sam Saffron

Schlimmer noch, es zeigt immer noch nicht die tatsächliche Geschichte des Verkehrs. Wow, Microsoft bläst Oracle die Socken ab!

4

Die besten Out-of-the-Box - Lösungen , die ich gefunden habe , sind eine Kombination aus dem langsamen Abfrageprotokoll verwenden (was im Vergleich zu den Profiler saugt) und Wireshark nur laufen auf Port 3306 (die wirklich zu Profiler zum kotzen verglichen und won‘ nicht funktionieren, wenn Sie Verbindungen verschlüsseln).

Es gibt auch SHOW FULL PROCESSLIST, eine reduzierte Kombination von sys.dm_exec_sessions und sys.dm_exec_requests (mit ein wenig sys.dm_exec_sql_text).


4

Wenn Sie eine einzelne Anwendung und nicht alle in MySQL vorhandenen Datenbanken profilieren müssen, ist Neor Profile SQL hilfreich.




Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.