3. MySQL Provided Options
Slow Query Log
General Query Log
Binary Log
Connectors
Processlist
Engine status
Status variables
ODTUG – June 2010
4. Other Techniques
MySQL Proxy
TCP/IP Capture
Dtrace/SystemTap
Application Management
ODTUG – June 2010
5. Slow Query Log
Not enabled by default
log-slow-queries = /path/to/file (5.0)
slow_query_log/slow_query_log_file (5.1)
Granularity of seconds
Microsecond patch by percona
Default slow time is 10 seconds
long_query_time = 2
Log output to file or table (5.1)
log_output = FILE | TABLE | BOTH
http://dev.mysql.com/doc/refman/5.1/en/slow-query-log.html
ODTUG – June 2010
6. Slow Query Log Example
# Time: 100518 19:34:31
# User@Host: user[db] @ localhost []
# Query_time: 4 Lock_time: 0 Rows_sent: 1155 Rows_examined: 1663671
select distinct visitorid from log where
timestamp like '20100518%' and accountid!=1 and
accountid!=37 and file not like '%admin%';
# Time: 100518 19:35:37
# User@Host: user[db] @ localhost []
# Query_time: 4 Lock_time: 0 Rows_sent: 6 Rows_examined: 1662525
select distinct accountid from log
where timestamp>='20100518132033' and accountid NOT IN ('0','1','37','1635');
# Time: 100518 19:35:41
# User@Host: user[db] @ localhost []
# Query_time: 4 Lock_time: 0 Rows_sent: 2477 Rows_examined: 1664996
select timestamp, file from log
where timestamp>='20100518000000' and timestamp<='end' and accountid!=1 and accountid!=37
order by timestamp desc;
# Time: 100518 19:35:44
# User@Host: user[db] @ localhost []
# Query_time: 3 Lock_time: 0 Rows_sent: 1157 Rows_examined: 1663676
select distinct visitorid from log
where timestamp like '20100518%' and accountid!=1 and accountid!=37
and file not like '%admin%';
ODTUG – June 2010
7. Slow Query Table Example
mysql> select start_time, query_time, rows_sent, rows_examined, db, sql_text
> from mysql.slow_log;
+++++++
| start_time | query_time | rows_sent | rows_examined | db | sql_text |
+++++++
| 20100614 13:43:37 | 00:03:45 | 1 | 31290045 | drupal | select count(*) from search_index |
+++++++
1 row in set (0.00 sec)
mysql>
ODTUG – June 2010
8. General Query Log
Not enabled by default
log = /path/to/file
general_log/general_log_file (5.1)
Log output to file or table (5.1)
log_output = FILE | TABLE | BOTH
Never use in production
Ideal for development, unit testing
environments
http://dev.mysql.com/doc/refman/5.1/en/query-log.html
ODTUG – June 2010
9. General Query Log Example
Output using Wordpress
26 Query SELECT * FROM wp_users WHERE user_login = 'xxxx'
26 Query SELECT meta_key, meta_value FROM wp_usermeta WHERE user_id = 2
26 Query SELECT option_value FROM wp_options WHERE option_name = 'sidebars_widgets' LIMIT 1
26 Query SELECT SQL_CALC_FOUND_ROWS wp_posts.* FROM wp_posts WHERE 1=1 AND
wp_posts.post_type = 'post' AND (wp_posts.post_status = 'publish' OR wp_posts.post_status = 'private')
ORDER BY wp_posts.post_date DESC LIMIT 0, 10
26 Query SELECT FOUND_ROWS()
26 Query SELECT t.*, tt.*, tr.object_id FROM wp_terms AS t INNER JOIN wp_term_taxonomy AS tt
ON tt.term_id = t.term_id INNER JOIN wp_term_relationships AS tr
ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tt.taxonomy IN ('category', 'post_tag') AND
tr.object_id IN (2849, 2842, 2836, 2824, 2812, 2680, 2813, 2800, 2770, 2784) ORDER BY t.name ASC
26 Query SELECT post_id, meta_key, meta_value FROM wp_postmeta WHERE post_id
IN (2849,2842,2836,2824,2812,2680,2813,2800,2770,2784)
ODTUG – June 2010
10. General Query Log Example (2)
Framework new connection
23 Connect user@host
23 Query SELECT 1
23 Query SET NAMES utf8
23 Query SET character_set_results = NULL
23 Query SHOW VARIABLES
23 Query SHOW COLLATION
23 Query SET autocommit=1
23 Query SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED
23 Query SET autocommit=0
ODTUG – June 2010
11. General Query Log Example (3)
Finding framework overhead
ROLLBACK after every SELECT
SELECT 1 – connection ping test
23 Query select count(*) from collection where account_name = 'xxx'
and user_id = '313'
23 Query rollback
23 Query select 1
23 Query select count(*) from collection where account_name = 'xxx'
and user_id = '346'
23 Query rollback
23 Query select 1
23 Query select name,user_id,date_format(`register_time`,'%Y%m%d%H%i%S') as
createTime from account where name = 'xxx' and
user_id = '346' and `status` = '1'
23 Query rollback
23 Query select 1
23 Query select max(mdate) from received where account_name = 'xxx'
And user_id = '346' order by mdate desc
23 Query rollback
ODTUG – June 2010
12. Binary Log
Not enabled by default
log-bin = /path/to/file
expire_log_days = 5
View with mysqlbinlog
http://dev.mysql.com/doc/refman/5.1/en/binary-log.html
ODTUG – June 2010
13. Binary Log Example
mysqlbinlog /path/to/log-bin.000000
# at 2461
#100604 10:49:43 server id 1 end_log_pos 2632 Query thread_id=6
exec_time=0 error_code=0
use blog/*!*/;
SET TIMESTAMP=1275662983/*!*/;
UPDATE `wp_postmeta` SET `meta_value` = '1275662983' WHERE
`meta_key` = '_edit_lock'
AND `post_id` = 2849
/*!*/;
# at 21107
#100604 10:58:49 server id 1 end_log_pos 21469 Query thread_id=62 exec_time=0
error_code=0
use monitoringmysql/*!*/;
SET TIMESTAMP=1275663529/*!*/;
SET @@session.time_zone='SYSTEM'/*!*/;
INSERT INTO wp_redirection_logs
(url,sent_to,created,agent,redirection_id,ip,referrer,module_id,group_id)
VALUES ('/mysqlmonitoring/dbtuna',NULL,NOW(),'Mozilla/5.0
(compatible; Yahoo! Slurp/3.0; http
://help.yahoo.com/help/us/ysearch/slurp)',NULL, '67.195.114.227', NULL, 3, NULL)
/*!*/;
ODTUG – June 2010
14. Connector/J
logSlowQueries
slowQueryThresholdMillis
SlowQueryThresholdNanos
http://dev.mysql.com/doc/refman/5.1/en/connector-j-reference-configuration-properties.html
ODTUG – June 2010
15. Processlist
Current connection/thread
No filtering options
Ideal for locking
mysql> SHOW [FULL] PROCESSLIST
$ mysqladmin [v] processlist
mysql> SELECT * FROM INFORMATION_SCHEMA.PROCESSLIST (5.1))
http://dev.mysql.com/doc/refman/5.1/en/show-processlist.html
ODTUG – June 2010
18. Engine Status
Provides engine specific information
Vendor implemented
InnoDB
Running threads
Last deadlock
Last foreign key error
Other engine types include
NDB, PBXT, TOKUDB
ODTUG – June 2010
19. Engine Status
mysql> SHOW ENGINE INNODB STATUS;
http://dev.mysql.com/doc/refman/5.1/en/show-engine.html
ODTUG – June 2010
20. Engine Status Example
TRANSACTIONS
Trx id counter 0 480206585
Purge done for trx's n:o < 0 480205682 undo n:o < 0 0
History list length 5
LIST OF TRANSACTIONS FOR EACH SESSION:
TRANSACTION 0 0, not started, process no 27230, OS thread id 1182685536
MySQL thread id 427, query id 123563 10.8.160.241 dba
SHOW ENGINE INNODB STATUS
TRANSACTION 0 0, not started, process no 27230, OS thread id 1169639776
MySQL thread id 44, query id 123445 10.8.160.241 dba
TRANSACTION 0 480206305, ACTIVE 67 sec, process no 27230, OS thread id 1192270176
mysql tables in use 1, locked 1
1 lock struct(s), heap size 368, 0 row lock(s), undo log entries 1
MySQL thread id 370, query id 123171 10.120.229.37 user query end
INSERT INTO `table` ....
TRANSACTION 0 480206290, ACTIVE 70 sec, process no 27230, OS thread id 1178159456
mysql tables in use 1, locked 1
1 lock struct(s), heap size 368, 0 row lock(s), undo log entries 1
MySQL thread id 372, query id 123150 10.120.229.37 user query end
INSERT INTO `table` ....
TRANSACTION 0 480206289, ACTIVE 70 sec, process no 27230, OS thread id 1178425696
mysql tables in use 1, locked 1
1 lock struct(s), heap size 368, 0 row lock(s), undo log entries 1
MySQL thread id 373, query id 123149 10.120.229.37 user query end
INSERT INTO `table` ....
....
ODTUG – June 2010
21. Engine Status Example (2)
------------------------
LATEST DETECTED DEADLOCK
------------------------
090624 14:32:18
*** (1) TRANSACTION:
TRANSACTION 0 39639074, ACTIVE 0 sec, process no 27807, OS thread id 1176562016 inserting
mysql tables in use 1, locked 1
LOCK WAIT 7 lock struct(s), heap size 1216
MySQL thread id 1225, query id 4695283 10.120.19.204 db update
INSERT INTO table VALUES(254381,638,1,57)
*** (1) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 0 page no 6371457 n bits 248 index `PRIMARY` of table `db/table` trx id 0 39639074 lock_mode X insert intention waiting
Record lock, heap no 1 PHYSICAL RECORD: n_fields 1; compact format; info bits 0
0: len 8; hex 73757072656d756d; asc supremum;;
*** (2) TRANSACTION:
TRANSACTION 0 39639079, ACTIVE 0 sec, process no 27807, OS thread id 1179224416 inserting, thread declared inside InnoDB 500
mysql tables in use 1, locked 1
7 lock struct(s), heap size 1216
MySQL thread id 1229, query id 4695295 prodgos23.eao.abn-iad.ea.com 10.120.19.204 madden_2010 update
INSERT INTO table VALUES(254382,746,1,57)
*** (2) HOLDS THE LOCK(S):
RECORD LOCKS space id 0 page no 6371457 n bits 248 index `PRIMARY` of table `madden_2010_franchise_xbl2/franchise_draft_board` trx id 0 39639079
lock_mode X
Record lock, heap no 1 PHYSICAL RECORD: n_fields 1; compact format; info bits 0
0: len 8; hex 73757072656d756d; asc supremum;;
*** (2) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 0 page no 6371457 n bits 248 index `PRIMARY` of table `db/table` trx id 0 39639079 lock_mode X insert intention waiting
Record lock, heap no 1 PHYSICAL RECORD: n_fields 1; compact format; info bits 0
0: len 8; hex 73757072656d756d; asc supremum;;
*** WE ROLL BACK TRANSACTION (2)
ODTUG – June 2010
22. Status Variables
Shows incrementing internal counters
Volume of SQL
Read/Write ratio
ODTUG – June 2010
23. Status Variables
mysql> SHOW GLOBAL STATUS;
$ mysqladmin extendedstatus
mysql> SELECT * FROM GLOBAL_STATUS (5.1)
http://dev.mysql.com/doc/refman/5.1/en/show-status.html
ODTUG – June 2010
27. MySQL Proxy
Included histogram.lua
Gives read/write breakdown per table
Shows top executing queries by frequency
Shows max and avg execution time
http://dev.mysql.com/doc/refman/5.1/en/mysql-proxy.html
https://launchpad.net/mysql-proxy
http://ronaldbradford.com/blog/sql-query-analysis-with-mysql-proxy-2009-09-02/
ODTUG – June 2010
32. DTrace/SystemTap
Observability technologies
Enable the behavior of running systems
and applications to be investigated
Zero probe effect when not enabled
http://www.sun.com/bigadmin/content/dtrace/index.jsp
http://sourceware.org/systemtap/
ODTUG – June 2010
36. Slow Query Log
mk-query-digest --type slowlog /path/to/slow.log
Best practice to roll/analyze daily
http://ronaldbradford.com/blog/the-correct-approach-to-rolling-mysql-logs-2010-02-22/
ODTUG – June 2010
37. Slow Query Analysis Example
● $ mkquerydigest type slowlog /var/log/mysql/slow.log
●
# Query 1: 0.00 QPS, 2.74x concurrency, ID 0x036A4959F0EBB3BD at byte 1 _
# pct total min max avg 95% stddev median
# Count 1 395
# Exec time 28 478528s 11s 4733s 1211s 4168s 1431s 511s
# Lock time 20 31777s 0 2769s 80s 685s 291s 0
# Rows sent 0 3.86k 10 10 10 10 0 10
# Rows exam 3 193.22M 500.73k 500.96k 500.90k 485.50k 0 485.50k
# Users 1 xxx
# Hosts 5 app5.xxxxx... (128), app1.xxxx... (85)... 3 more
# Databases 1 xxxx
# Time range 20090518 10:23:18 to 20090520 10:50:14
# bytes 0 184.67k 476 479 478.73 463.90 0 463.90
# Query_time distribution
# 1us
# 10us
# 100us
# 1ms
# 10ms
# 100ms
# 1s
# 10s+ ################################################################
ODTUG – June 2010
38. Slow Query Analysis Example
# Tables
# SHOW TABLE STATUS FROM `xxxx` LIKE 'gg'G
# SHOW CREATE TABLE `xxxx`.`gg`G
# SHOW TABLE STATUS FROM `xxxx ` LIKE 'gr'G
# SHOW CREATE TABLE `xxxx `.`gr`G
# SHOW TABLE STATUS FROM `xxxx ` LIKE 'tt'G
# SHOW CREATE TABLE `xxxx `.`tt`G
# EXPLAIN
SELECT tt.*,
(SELECT COUNT(*) FROM gg WHERE gg.tt_user_id = tt.id) AS g_c,
(SELECT COUNT(*) FROM WHERE gr.tt_user_id = tt.id ) AS r_c
FROM tt AS tt
WHERE 1 AND tt.user_type = 'CUSTOMER'
GROUP BY tt.id HAVING g_c > 1 OR r_c > 1
ORDER BY tt.id desc, g_c DESC , r_c DESC
LIMIT 10 OFFSET 0G
ODTUG – June 2010
39. General Query Log
● $ mkquerydigest type genlog reportformat profile /opt/mysql_sandboxes/latest/data/msandbox.log
# 2.4s user time, 40ms system time, 37.40M rss, 78.70M vsz
# Current date: Fri Jun 11 14:17:22 2010
# Files: /opt/mysql_sandboxes/latest/data/msandbox.log
# Overall: 17.11k total, 2.64k unique, 0.71 QPS, 0x concurrency __________
# total min max avg 95% stddev median
# Exec time 0 0 0 0 0 0 0
# Time range 20100611 07:35:44 to 20100611 14:17:01
# bytes 793.75k 11 26.50k 47.52 54.21 295.84 38.53
# Profile
# Rank Query ID Response time Calls R/Call Item
# ==== ================== ================ ===== ======== ================
# 1 0xC9EEB2D51C356A33 0.0000 0.0% 3622 0.0000 SET
# 2 0x6C099B0B73EA7633 0.0000 0.0% 608 0.0000 USE
# 3 0xAC5C18B304F9DE87 0.0000 0.0% 595 0.0000 SELECT
# 4 0x30FE5C2032672827 0.0000 0.0% 595 0.0000 SHOW TABLE STATUS
# 5 0x1D7CBA0BE5BAA758 0.0000 0.0% 595 0.0000 SHOW TRIGGERS
# 6 0xAEA9A980826923AF 0.0000 0.0% 595 0.0000 SET
# 7 0x10AB55EA465447D0 0.0000 0.0% 565 0.0000 ADMIN FIELD
# 8 0x5D51E5F01B88B79E 0.0000 0.0% 522 0.0000 ADMIN CONNECT
# 9 0xAA353644DE4C4CB4 0.0000 0.0% 438 0.0000 ADMIN QUIT
# 10 0xE3A3649C5FAC418D 0.0000 0.0% 410 0.0000 SELECT
# 11 0x28FC5B5D583E2DA6 0.0000 0.0% 402 0.0000 SHOW STATUS
# 12 0x3AEAAD0E15D725B5 0.0000 0.0% 107 0.0000 SET
# 13 0x3607184B9D9C3A96 0.0000 0.0% 107 0.0000 SELECT
# 14 0x44001A2E53C1AB70 0.0000 0.0% 107 0.0000 SET
# 15 0xA2750AF24EA2AEE6 0.0000 0.0% 107 0.0000 SHOW COLLATION
# 16 0x38B3D80280BBFA2A 0.0000 0.0% 107 0.0000 SET
# 17 0xC69B6ED2C47380A4 0.0000 0.0% 107 0.0000 SHOW VARIABLES
# 18 0xE4CF7146873CCC28 0.0000 0.0% 107 0.0000 SET
# 19 0x5CBA2034458B5BC9 0.0000 0.0% 95 0.0000 SHOW DATABASES
# 20 0x2DE40AAFA6F4B715 0.0000 0.0% 46 0.0000 INSERT SELECT TEMP.task
ODTUG – June 2010
40. General Query Log Analysis
$ mkquerydigest type genlog /opt/mysql_sandboxes/latest/data/msandbox.log
# Query 20: 0 QPS, 0x concurrency, ID 0x2DE40AAFA6F4B715 at byte 56687 ___
# This item is included in the report because it matches limit.
# pct total min max avg 95% stddev median
# Count 0 46
# Exec time 0 0 0 0 0 0 0 0
# Databases 1 anonymous
# Time range 20100611 09:33:04 to 20100611 09:33:04
# bytes 3 25.72k 404 1.12k 572.57 833.10 157.30 511.45
# Query_time distribution
# 1us
# 10us
# 100us
# 1ms
# 10ms
# 100ms
# 1s
# 10s+
# Tables
# SHOW TABLE STATUS FROM `TEMP` LIKE 'task'G
# SHOW CREATE TABLE `TEMP`.`task`G
insert into TEMP.task( task_type, state, user_table_schema, user_table_table, user
_table_depth, artifact_schema, artifact_table, command )
values( 'GenerateFinalBySort', 'waiting', 'drupal', 'node_revisions', '0',
'TEMP', 'node_revisions$final', 'create table `TEMP`.`node_revisions$final`(`nid` int,
`vid` int, `uid` int, `title` varchar(255), `body` longtext, `teaser` longtext, `log` longtext,
`timestamp` int, `format` int) select `nid`, `vid`, `uid`, `title`, `body`, `teaser`, `log`,
`timestamp`, `format` from `drupal`.`node_revisions` order by `vid`')G
ODTUG – June 2010
41. Binary Log
mysql> SHOW GLOBAL VARIABLES LIKE 'log_bin';
mysql> SHOW MASTER STATUS;
mysql> SHOW MASTER LOGS;
ODTUG – June 2010
42. Aggregating Binlog Output
mysqlbinlog /path/to/mysqlbin.000999 |
grep i e "^update" e "^insert" e "^delete" e "^replace" e "^alter" |
cut c1100 | tr '[AZ]' '[az]' |
sed e "s/t/ /g;s/`//g;s/(.*$//;s/ set .*$//;s/ as .*$//" |
sed e "s/ where .*$//" |
sort | uniq c | sort nr
33389 update e_acc
17680 insert into r_b
17680 insert into e_rec
14332 insert into rcv_c
13543 update e_rec
10805 update loc
3339 insert into r_att
2781 insert into o_att
ODTUG – June 2010
44. Status variables Analysis
Gathering global status per time interval
Reporting options
statpack
http://ronaldbradford.com/blog/using-statpack-with-show-status-2009-06-18/
ODTUG – June 2010
45. statpack Example
====================================================================================================
Uptime: 17 days 17 hours 22 mins Snapshot Period 1: 59 minute interval
====================================================================================================
Variable Delta/Percentage Per Second Total
=================================================================================...
====================================================================================================
Statement Activity
====================================================================================================
SELECT: 13,503,876 3,798.56 4,298,170,239 (94.25%)
INSERT: 91,101 25.63 25,327,062 (0.56%)
UPDATE: 782,004 219.97 220,640,296 (4.84%)
DELETE: 9,674 2.72 2,485,643 (0.05%)
COMMIT: 46,422 13.06 13,700,478 (0.30%)
ROLLBACK: 0 0.00 13 (0.00%)
...
====================================================================================================
Temporary Space
====================================================================================================
tmp_table_size Efficiency: 2.10%
Memory Temp Tables: 26,467 7.45 9,335,030
Disk Temp Tables: 25,951 7.30 9,138,705
Temp Files: 2 0.00 601
ODTUG – June 2010
46. TCP/IP Dump Analysis
Non-intrusive
Close to full sample
Near realtime
$ tcpdump i eth0 port 3306 s 65535 x
> n q tttt c 1000 > tcpdump.out
$ cat tcpdump.out | mkquerydigest type tcpdump
ODTUG – June 2010
48. TCP/IP Dump Query Review
# Query 6: 23.02 QPS, 0.01x concurrency, ID 0x8D86ED007917BCE6 at byte 2
# This item is included in the report because it matches limit.
# pct total min max avg 95% stddev median
# Count 6 131
# Exec time 3 48ms 160us 5ms 366us 690us 477us 247us
# Hosts 5 10.0.0.77 (86), 10.0.0.36 (21), 10.0.0.79 (20)... 2 more
# Time range 20100330 17:52:43.034021 to 20100330 17:52:48.724815
# bytes 8 15.93k 123 125 124.54 124.25 1 124.25
# Errors 1 none
# Rows affe 0 0 0 0 0 0 0 0
# Warning c 0 0 0 0 0 0 0 0
# Query_time distribution
# 1us
# 10us
# 100us ################################################################
# 1ms ##
# 10ms
# 100ms
# 1s
# 10s+
# Tables
# SHOW TABLE STATUS LIKE 'loc'G
# SHOW CREATE TABLE `loc`G
# EXPLAIN
SELECT l.* FROM loc p, loc l WHERE p.id=2090 AND l.lft BETWEEN p.lft AND p.rgt AND
l.depth=p.depth+1 ORDER BY l.lftG
ODTUG – June 2010
49. mycheckpoint
SQL orientated monitoring utility for
MySQL
Measures various metrics
Stores measurements in database
Metrics can be accessed through SQL
Can generate HTML reports and Google
charts easily
http://code.openark.org/forge/mycheckpoint/documentation
ODTUG – June 2010
50. SQL Analysis Tools
EXPLAIN
mk-visual-explain
SHOW CREATE TABLE
SHOW INDEXES
SHOW TABLE STATUS
I_S Table/Index size
SHOW SESSION STATUS
SHOW PROFILE
ODTUG – June 2010
51. Explain
Returns information on query plan
Query not actually executed (unless
query contains sub-query)
1 row in output per table
EXPLAIN EXTENDED shows query actually
executed
http://dev.mysql.com/doc/refman/5.1/en/explain.html
ODTUG – June 2010
53. Explain Examples
mysql> explain
> select
> avg(length(w.variables)) / 1048576
> from
> watchdog w
> G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: w
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 69248
Extra:
1 row in set (0.00 sec)
mysql>
ODTUG – June 2010
54. mk-visual-explain
Reverse engineers explain output from
MySQL
Formats MySQL explain output as a left-
deep tree
Can take piped input or can process
explain plans from input file
http://www.maatkit.org/doc/mk-visual-explain.html
ODTUG – June 2010
56. Show Create Table
Shows full definition
Includes all keys
Shows storage engine
SHOW CREATE TABLE [schema.]tablename
http://dev.mysql.com/doc/refman/5.1/en/show-create-table.html
ODTUG – June 2010
57. Show Create Table Example
mysql> SHOW CREATE TABLE wp_postmetaG
*************************** 1. row ***************************
Table: wp_postmeta
Create Table: CREATE TABLE `wp_postmeta` (
`meta_id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`post_id` bigint(20) unsigned NOT NULL DEFAULT '0',
`meta_key` varchar(255) DEFAULT NULL,
`meta_value` longtext,
PRIMARY KEY (`meta_id`),
KEY `post_id` (`post_id`),
KEY `meta_key` (`meta_key`)
) ENGINE=MyISAM AUTO_INCREMENT=1745 DEFAULT CHARSET=utf8
1 row in set (0.00 sec)
ODTUG – June 2010
58. Show Indexes
Provides cardinality
SHOW INDEX[ES] [FROM|IN] [schema.]tablename
http://dev.mysql.com/doc/refman/5.1/en/show-index.html
ODTUG – June 2010
60. Table Status
SHOW TABLE STATUS [IN schema] LIKE 'tablename'
http://dev.mysql.com/doc/refman/5.1/en/show-table-status.html
ODTUG – June 2010
61. Table Status Example
mysql> SHOW TABLE STATUS LIKE 'wp_postmeta'G
*************************** 1. row ***************************
Name: wp_postmeta
Engine: MyISAM
Version: 10
Row_format: Dynamic
Rows: 1351
Avg_row_length: 46
Data_length: 62960
Max_data_length: 281474976710655
Index_length: 58368
Data_free: 76
Auto_increment: 1745
Create_time: 20090908 09:57:51
Update_time: 20100604 15:06:47
Check_time: 20100601 11:12:54
Collation: utf8_general_ci
Checksum: NULL
Create_options:
Comment:
1 row in set (0.00 sec)
ODTUG – June 2010
62. Information Schema
INFORMATION_SCHEMA
TABLES
COLUMNS
Meta data
Simple view of DBA_TABLES/COLUMNS
http://dev.mysql.com/doc/refman/5.1/en/information-schema.html
ODTUG – June 2010
63. Information Schema Example
SELECT table_schema,
table_name,
engine,
row_format,
table_rows,
avg_row_length,
(data_length+index_length)/1024/1024 as total_mb,
(data_length)/1024/1024 as data_mb,
(index_length)/1024/1024 as index_mb,
CURDATE() AS today
FROM information_schema.tables
WHERE table_schema=DATABASE()
ORDER BY 7 DESC;
http://ronaldbradford.com/mysql-dba/#perschema
ODTUG – June 2010
65. Show Session Status
MySQL Internal counters
http://dev.mysql.com/doc/refman/5.1/en/show-status.html
ODTUG – June 2010
66. Show Session Status Example
SHOW SESSION STATUS LIKE 'Created%';
+++
| Variable_name | Value |
+++
| Created_tmp_disk_tables | 1 |
| Created_tmp_files | 5 |
| Created_tmp_tables | 3 |
+++
SELECT ...;
SHOW SESSION STATUS LIKE 'Created%';
+++
| Variable_name | Value |
+++
| Created_tmp_disk_tables | 2 |
| Created_tmp_files | 5 |
| Created_tmp_tables | 3 |
+++
ODTUG – June 2010
67. Show Profile
Provides internal message calls
Descriptions not always accurate
SET PROFILING = 1;
SHOW PROFILES;
SHOW PROFILE [FOR QUERY n];
http://dev.mysql.com/doc/refman/5.1/en/show-profiles.html
ODTUG – June 2010
68. Show Profile Example
mysql> SHOW PROFILESG
*************************** 1. row ***************************
Query_ID: 1
Duration: 0.00081600
Query: SELECT t.*, tt.*, tr.object_id FROM wp_terms
AS t INNER JOIN wp_term_taxonomy AS tt ON
tt.term_id = t.term_id INNER JOIN
wp_term_relationships AS tr ON
tr.term_taxonomy_id = tt.term_taxonomy_id
WHERE tt.taxonomy IN
('category', 'post_tag') AND
tr.object_id IN (2487)
ORDER BY t.name ASC
ODTUG – June 2010
69. Show Profile Example (2)
mysql> SHOW PROFILE SOURCE FOR QUERY 1;
++++++
| Status | Duration | Source_function | Source_file | Source_line |
++++++
| starting | 0.000049 | NULL | NULL | NULL |
| checking query cache for query | 0.000074 | unknown function | sql_cache.cc | 1446 |
| Opening tables | 0.000013 | unknown function | sql_base.cc | 4495 |
| System lock | 0.000005 | unknown function | lock.cc | 258 |
| Table lock | 0.000032 | unknown function | lock.cc | 269 |
| init | 0.000038 | unknown function | sql_select.cc | 2484 |
| optimizing | 0.000014 | unknown function | sql_select.cc | 820 |
| statistics | 0.000135 | unknown function | sql_select.cc | 1011 |
| preparing | 0.000017 | unknown function | sql_select.cc | 1033 |
| Creating tmp table | 0.000155 | unknown function | sql_select.cc | 1524 |
| executing | 0.000002 | unknown function | sql_select.cc | 1755 |
| Copying to tmp table | 0.000142 | unknown function | sql_select.cc | 1902 |
| Sorting result | 0.000026 | unknown function | sql_select.cc | 2176 |
| Sending data | 0.000051 | unknown function | sql_select.cc | 2309 |
| end | 0.000002 | unknown function | sql_select.cc | 2530 |
| removing tmp table | 0.000063 | unknown function | sql_select.cc | 10776 |
| end | 0.000003 | unknown function | sql_select.cc | 10801 |
| query end | 0.000002 | unknown function | sql_parse.cc | 4978 |
| freeing items | 0.000017 | unknown function | sql_parse.cc | 6004 |
| storing result in query cache | 0.000005 | unknown function | sql_cache.cc | 983 |
| logging slow query | 0.000001 | unknown function | sql_parse.cc | 1679 |
| cleaning up | 0.000002 | unknown function | sql_parse.cc | 1647 |
++++++
22 rows in set (0.00 sec)
ODTUG – June 2010
70. Show Profile Example (3)
mysql> SHOW PROFILES;
+++
| 1 | 0.00084800 | SELECT t.*, tt.*, tr.object_id FROM wp_terms AS t ...
| 2 | 0.00006000 | SELECT t.*, tt.*, tr.object_id FROM wp_terms AS t ....
+++
2 rows in set (0.00 sec)
mysql> SHOW PROFILE SOURCE FOR QUERY 2;
++++++
| starting | 0.000034 | NULL | NULL | NULL |
| checking query cache for query | 0.000008 | unknown function | sql_cache.cc | 1446 |
| checking privileges on cached | 0.000004 | unknown function | sql_cache.cc | 1534 |
| sending cached result to clien | 0.000010 | unknown function | sql_cache.cc | 1629 |
| logging slow query | 0.000002 | unknown function | sql_parse.cc | 1679 |
| cleaning up | 0.000002 | unknown function | sql_parse.cc | 1647 |
++++++
ODTUG – June 2010
72. About the MySQL Optimizer
Cost based optimizer
No way to pin QEP
One index per table rule (with exceptions)
The lack of good hints
No statistics granularity
No parallelism
http://forge.mysql.com/wiki/How_does_the_MySQL_Optimizer_work
ODTUG – June 2010
73. SQL Optimization Goals
Identify the best indexes
Reduce unnecessary data access
Minimize kernel internals
ODTUG – June 2010
74. Explain Signs
No index used
Large rows
Excessive possible indexes
SQL for composite/covering indexes
Using Temporary
Using filesort
Derived tables
ODTUG – June 2010
75. MySQL Index Types
Column indexes
Composite indexes
Covering indexes
Partial indexes
Spatial indexes
Fulltext indexes
Clustered indexes
Hash indexes
http://ronaldbradford.com/blog/understanding-different-mysql-index-implementations-2009-07-22/
ODTUG – June 2010
81. Partial Indexes
CREATE TABLE parts(
...
brand_id INT UNSIGNED NOT NULL,
part_number VARCHAR(30) NOT NULL,
manufacturer_name VARCHAR(100) NOT NULL,
...
INDEX (brand_id, part_number,manufacturer_name)
)
ALTER TABLE parts DROP INDEX brand_id,
ADD KEY (brand_id,
interchange_part_number,
manufacturer_name(8));
Reduced Index size by 30%.
ODTUG – June 2010
82. QEP – Using Filesort
EXPLAIN SELECT itemid FROM items WHERE productid=999 GROUP BY itemid;
+++++++++++
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra
|
+++++++++++
| 1 | SIMPLE | items | ref | productid | productid | 4 | const | 1 | Using where; Using filesort
Using filesort
|
+++++++++++
1 row in set (0.00 sec)
EXPLAIN SELECT DISTINCT
DISTINCT itemid FROM items WHERE productid=999
+++++++++++
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+++++++++++
| 1 | SIMPLE | items | ref | productid | productid | 4 | const | 1 | |
+++++++++++
ODTUG – June 2010
89. MySQL Index Sizes
NULL columns
Bigint vs int
InnoDB secondary index PK value
ODTUG – June 2010
90. When Indexes Don't Help
CREATE TABLE `items` (
`itemid` int(11) NOT NULL auto_increment,
`productid` int(11) NOT NULL default '0',
...
`itemlive` enum('true','false') NOT NULL
default 'true',
...
PRIMARY KEY (`itemid`),
KEY `productid` (`productid`),
KEY `productid` (`productid`)
KEY `packaging_cost` (`packaging_cost`)
)
ODTUG – June 2010
91. When Indexes Don't Help
EXPLAIN
SELECT DISTINCT(categories.categoryid)
FROM categories, category_product, items
WHERE categories.categoryname!=''
AND categories.categoryid=category_product.categoryid
AND category_product.productid=items.productid
AND category_product.productid=items.productid
AND items.itemlive='true';
+++++++++++
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+++++++++++
NULL | NULL | NULL | 2906 | Using where; Using temporary |
| 1 | SIMPLE | items | ALL | productid | NULL
| 1 | SIMPLE | category_product | ref | categoryid,productid | productid | 4 | baris5.items.productid | 1 | |
| 1 | SIMPLE | categories | eq_ref | PRIMARY | PRIMARY | 4 | baris5.category_product.categoryid | 1 | Using where |
+++++++++++
3 rows in set (0.00 sec)
ODTUG – June 2010
92. When Indexes Don't Help
Adding an index can reduce this full table scan
mysql> alter table items drop index productid, add index (productid,itemlive);
+++++++++
++
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra
|
+++++++++
++
| 1 | SIMPLE | items | index | productid | productid | 5 | NULL | 2180 | Using
where; Using index; Using temporary |
| 1 | SIMPLE | category_product | ref | categoryid,productid | productid | 4 | ronald.items.productid | 1 |
|
| 1 | SIMPLE | categories | eq_ref | PRIMARY | PRIMARY | 4 | baris5.category_product.categoryid | 1 | Using
where |
+++++++++
++
ODTUG – June 2010
93. Optimizing SQL for Locking
DML is a blocking statement for MyISAM
Long running cleanup scripts
DELETE FROM fts_datacache
WHERE productid NOT IN (
SELECT productid
FROM xcart_products_categories
WHERE categoryid IN (297,1356,1366,1361,1202,...)
GROUP BY productid
3+ minutes to run SELECT
ODTUG – June 2010
94. Optimizing SQL for Locking
Rewriting statement into 2 statements
can reduce locking time to ~10 ms
CREATE TEMPORARY TABLE delete_cache (
productid INT NOT NULL,
primary key (productid)) ENGINE=MEMORY
SELECT DISTINCT productid
FROM retailbl_xcart.xcart_products_categories
WHERE categoryid IN (297,1356,1366,1361,1202,...);
DELETE FROM fts_datacache
WHERE productid NOT IN
(SELECT productid FROM delete_cache);
ODTUG – June 2010
97. The Most Optimal
SQL is the SQL You
Can Eliminate
ODTUG – June 2010
98. Eliminating SQL – Example 1
Following executed 6,000 times in 5 min period
SELECT pages_id,
pages_livestats_code,
pages_title,
pages_parent,
pages_exhibid,
pages_theme,
pages_accession_num
FROM pages
WHERE pages_id = 0
0 is an invalid pages_id
ODTUG – June 2010
99. Eliminating SQL – Example 2
Following executed on single page load
5 Query SELECT * FROM `artist`
5 Query SELECT * FROM `artist`
5 Query SELECT * FROM `artist`
5 Query SELECT * FROM `artist`
5 Query SELECT * FROM `artist`
5 Query SELECT * FROM `artist` WHERE (ArtistID = 196 )
5 Query SELECT * FROM `artist` WHERE (ArtistID = 2188)
5 Query SELECT * FROM `artist`
5 Query SELECT * FROM `artist`
5 Query SELECT * FROM `artist`
ODTUG – June 2010
100. Eliminating SQL – Example 3
Row at a time (RAT) processing
SELECT * FROM activities_theme WHERE theme_parent_id=0
SELECT * FROM activities_theme WHERE theme_parent_id=1
SELECT * FROM activities_theme WHERE theme_parent_id=2
SELECT * FROM activities_theme WHERE theme_parent_id=11
SELECT * FROM activities_theme WHERE theme_parent_id=16
Chunk at a time (CAT) processing
SELECT *
FROM activities_theme
WHERE theme_parent_id in (0,1,2,11,16)
ODTUG – June 2010
102. Capture/Analysis/Optimization
Improvement is a reoccurring process
Ideally you should analyze all SQL
Changes in data size and result set size
over time can affect SQL performance
ODTUG – June 2010