มีเครื่องมือเช่น "SQL Server Profiler" ของ Microsoft สำหรับ MySQL หรือไม่? [ปิด]


43

ในขณะที่พัฒนาบน MySQL ฉันพลาดที่จะสามารถสร้างโปรไฟล์ได้ ฉันพบว่าSQLyogเป็นตัวแทนที่ที่ดีสำหรับ Query Analyzer แต่ไม่พบเครื่องมือที่ทำงานเช่น SQL profiler

สำหรับชาว MySQL ที่ไม่ได้เห็นSQL Profilerของ Microsoft นี่เป็นภาพหน้าจอ

profiler sql

ที่งานก่อนหน้าของฉันเรามีเครื่องมือที่trumped SQL Profilerและทำให้เรามีร่องรอยสแต็ก

ผู้สร้างโปรไฟล์ altiris

ไม่มีใครรู้ว่าเครื่องมือใด ๆ เช่นเดียวกับที่ฉันกล่าวถึงที่ทำงานร่วมกับ MySQL

(FYI ฉันสามารถให้ Altiris Profiler ทำงานกับ MySQL ได้ แต่จะเกี่ยวข้องกับการใช้งาน Windows และไม่ใช่ Symantec sku ดังนั้นการออกใบอนุญาตจึงยุ่งยากมาก)

คำตอบ:


17

MySQL ไม่เคยเกิดขึ้นกับการสืบค้นโปรไฟล์ ตอนนี้ MySQL กำลังถูกปู่ของ Oracle ฉันรู้ว่าสิ่งนี้จะยังคงเป็นกรณี

แต่ความหวังทั้งหมดจะไม่สูญหายไป

ตั้งแต่ปี 2550 Percona ได้คิดค้นเครื่องมือที่ยอดเยี่ยมสำหรับทุกสิ่งที่นักพัฒนาและ DBA ต้องการรวมถึง Query Profiling

เครื่องมือชุดแรกของPerconaหรือที่รู้จักกันในชื่อMAATKITสร้างขอบเขตสำหรับผู้ใช้ที่จริงจังของ MySQL มันมีหลายสิ่งหลายอย่างเช่น:

  • การทำโปรไฟล์แบบสอบถาม
  • การจำลองการเต้นของหัวใจ
  • การจัดการการจำลองแบบทาส
  • การตรวจสอบตารางและการประสานข้อมูล

Percona ได้คดเคี้ยวเมื่อเร็ว ๆ นี้ MAATKIT เป็นชุดขึ้นไปวันที่เครื่องมือที่รู้จักกันในวันนี้เป็นPercona Toolkit เครื่องมือเหล่านี้หยิบขึ้นมาโดยที่ MAATKIT ถูกทิ้งไว้โดยการขยายขอบเขตของกิจกรรมสำหรับผู้ใช้ MySQL ที่ร้ายแรงเพื่อรวมสิ่งต่าง ๆ เช่น:

  • การตรวจสอบข้อผิดพลาดที่สำคัญต่างประเทศ
  • การเปลี่ยนสคีมาออนไลน์
  • ภาพอธิบายแผน
  • และอื่น ๆ ...

กลับไปที่คำถามเดิมเครื่องมือในการทำโปรไฟล์แบบสอบถามมี

นี่คือตัวอย่างของข้อมูลที่สมบูรณ์ที่สามารถมาจากการใช้หนึ่งในเครื่องมือเหล่านี้:

ฉันช่วยให้ลูกค้าใช้งาน mk-query-digest เพื่อรายงาน 20 แบบสอบถามที่มีประสิทธิภาพแย่ที่สุดในทุก ๆ 20 นาที ฉันได้ความคิดจากวิดีโอ YouTubeนี้ ลูกค้าจะย้ายผลลัพธ์ของแบบสอบถามที่ไม่ดีไปยัง memcached ซึ่งจะช่วยลดการเกิดปัญหาของการสอบถามที่เก็บค่าผ่านทางในฐานข้อมูล

นี่คือสคริปต์ที่ฉันโทรไป mk-query-digest (ออกรายการกระบวนการเท่านั้น)

#!/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}

นี่คือผู้ใช้ที่ฉันทำเพื่อเชื่อมต่อกับ mysql โดยใช้ mk-query-digest

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

นี่คือ crontab ที่ฉันวิ่งทุก ๆ 20 นาที (น้อยกว่า 10 วินาที) ที่เก็บ 144 ชุดสุดท้าย (ซึ่งเป็น 48 ชั่วโมงของการทำโปรไฟล์)

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

ส่วนที่เหลือเชื่อ: ผลลัพธ์ของ mk-query-digest

นี่คือโปรไฟล์ที่วิ่ง 2011-12-28 11:20:00 สำหรับ 1190 วินาที (20 นาทีน้อยกว่า 10 วินาที)

22 บรรทัดสุดท้าย

# 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

ขอให้สังเกตว่านี่เป็นรายการของ 20 แบบสอบถามที่มีประสิทธิภาพแย่ที่สุดโดยยึดตามเวลาตอบสนองของแบบสอบถามหารด้วยจำนวนครั้งที่มีการเรียกแบบสอบถาม

ดูที่ Query ID # 1 ซึ่งก็คือ0x5E994008E9543B29เราพบ ID การสืบค้นนั้นในไฟล์เอาต์พุตและนี่คือรายงานสำหรับการสืบค้นเฉพาะนั้น:

# 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

แม้ว่าฮิสโตแกรมนั้นเป็นแบบข้อความ แต่ให้ภาพที่ถูกต้องเกี่ยวกับประสิทธิภาพโดยรวมของแบบสอบถามบางครั้งใช้งานเกิน 1 วินาทีและใช้เวลาส่วนใหญ่ระหว่าง 0.01 ถึง 0.1 วินาที จากที่นี่คุณสามารถทำการปรับประสิทธิภาพโดยดำเนินการปรับโครงสร้างแบบสอบถามอีกครั้งวางผลลัพธ์ของแบบสอบถามใน memcached เพิ่มดัชนีที่หายไปหรือครอบคลุม ฯลฯ

สรุปผลการศึกษา

IMHO ถ้า Percona วางเครื่องมือตัวสร้างโปรไฟล์ลงใน Windows GUI มันจะเทียบเคียงกับ SQL Server Profiler ของ Microsoft ได้อย่างง่ายดาย

ป้องกันวาง !!!


IMHO JetProfiler ดูเหมือนว่า Percona Tools จะรวมกราฟิกไว้ด้วยกัน แต่ละคนมีความแตกต่างกัน ผู้ใช้ Linux และผู้ใช้บรรทัดคำสั่งจะพึงพอใจกับ Percona Tools หรือ MAATKIT JetProfiler ไม่จำเป็นต้องเป็นฐานข้อมูลเชิงลึกรวมถึงข้อได้เปรียบเชิงกราฟิกของ Windows ของ MONyog ในการกำจัดของคุณ
RolandoMySQLDBA


5

ไม่ไม่มีเครื่องมือดังกล่าว


ตกลง ฉันพบว่านักพัฒนา / ผู้ดูแลระบบ MySQL ส่วนใหญ่ไม่เคยใช้เวลากับ Microsoft SQL Server มากนักและไม่ทราบว่า MS stack นั้นมีความน่าเหลือเชื่อสำหรับการพัฒนาอย่างไร เครื่องมือสืบค้น MySQL ทุกตัวที่ฉันเห็นขึ้นอยู่กับการลงคะแนนเลือกตั้ง แต่ SQL Server ช่วยให้คุณดูเกือบทุกอย่างที่เกิดขึ้นกับฐานข้อมูลแบบเรียลไทม์ ไม่มีอะไรที่ใกล้เคียงกับรายละเอียดของ SQL Server Profiler เพราะ MySQL ไม่รองรับ
parleer

4

MySQL Query Profiler เมื่อรวมกับเครื่องมือ GUI MySQLนั้นน่าจะใกล้เคียงกับที่คุณสามารถเข้าถึงเครื่องมือ SQL Server Profiler


2
อุ๊ยไม่มี GUI มี ...
แซม Saffron

ที่แย่กว่านั้นคือมันยังไม่แสดงประวัติการเข้าชมที่แท้จริง ว้าวไมโครซอฟท์ระเบิดถุงเท้าออราเคิลบนอันนี้!

4

ทางออกที่ดีที่สุดที่ฉันเคยพบคือการใช้การรวมกันของบันทึกการสืบค้นที่ช้า (ซึ่งแย่กว่าเมื่อเปรียบเทียบกับ Profiler) และเพิ่งใช้ Wireshark บนพอร์ต 3306 (ซึ่งแย่มากเมื่อเทียบกับ Profiler และชนะ ' ไม่ทำงานหากคุณกำลังเข้ารหัสการเชื่อมต่อ)

นอกจากนี้ยังมี SHOW FULL PROCESSLIST ซึ่งเหมือนกับการรวมกันที่ลดลงของ sys.dm_exec_sessions และ sys.dm_exec_requests (ด้วย sys.dm_exec_sql_text เพียงเล็กน้อย)


4

หากคุณต้องการโพรไฟล์แอปพลิเคชันเดียวและไม่ใช่ฐานข้อมูลทั้งหมดที่อยู่ใน MySQL คุณจะพบว่าNeor Profile SQLมีประโยชน์


3

เรามีเซิร์ฟเวอร์ขนาดใหญ่ 6 ตัวที่ใช้งาน MySQL เวอร์ชั่นต่างๆตั้งแต่ 4.1.22 ถึง 5.1 เครื่องมือที่ดีของJet Profilerที่ช่วยให้เราเห็นสถานะของเซิร์ฟเวอร์ทั้งหมดได้อย่างชัดเจน Visual profiler http://tinyurl.com/profiler-png


3

ฉันอยากจะแนะนำสิ่งที่ใกล้เคียงที่สุดกับสิ่งนี้คือเครื่องมือเพิ่มประสิทธิภาพการติดตาม (ใหม่ใน 5.6)

อีกตัวอย่างหนึ่งอาจเป็นSHOW PROFILES(5.1+) หรือperformance_schemaซึ่งมีการวิเคราะห์ระดับคำสั่งจาก MySQL 5.6+


โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.