Changeset 40
- Timestamp:
- 09/08/08 01:16:39 (2 months ago)
- Files:
-
- mysqltuner.pl (modified) (23 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
mysqltuner.pl
r39 r40 1 1 #!/usr/bin/perl -w 2 # mysqltuner.pl - Version 0.9. 82 # mysqltuner.pl - Version 0.9.9 3 3 # High Performance MySQL Tuning Script 4 4 # Copyright (C) 2006-2008 Major Hayden - major@mhtx.net … … 21 21 # 22 22 # This project would not be possible without help from: 23 # Matthew Montgomery 24 # Paul Kehrer 25 # Dave Burgess 26 # Jonathan Hinds 27 # Mike Jackson 28 # Nils Breunese 29 # Shawn Ashlee 30 # Luuk Vosslamber 31 # Ville Skytta 32 # Trent Hornibrook 33 # Jason Gill 23 # Matthew Montgomery Paul Kehrer 24 # Dave Burgess Jonathan Hinds 25 # Mike Jackson Nils Breunese 26 # Shawn Ashlee Luuk Vosslamber 27 # Ville Skytta Trent Hornibrook 28 # Jason Gill Mark Imbriaco 29 # Greg Eden Aubin Galinotti 30 # Giovanni Bechis Bill Bradford 34 31 # 35 32 # Inspired by Matthew Montgomery's tuning-primer.sh script: … … 42 39 43 40 # Set up a few variables for use in the script 44 my $tunerversion = "0.9. 8";41 my $tunerversion = "0.9.9"; 45 42 my (@adjvars, @generalrec); 46 43 … … 54 51 "forceswap" => 0, 55 52 "host" => 0, 53 "socket" => 0, 56 54 "port" => 0, 57 55 "user" => 0, … … 70 68 'forceswap=i', 71 69 'host=s', 70 'socket=s', 72 71 'port=i', 73 72 'user=s', … … 95 94 " Connection and Authentication\n". 96 95 " --host <hostname> Connect to a remote host to perform tests (default: localhost)\n". 96 " --socket <socket> Use a different socket for a local connection\n". 97 97 " --port <port> Port to use for connection (default: 3306)\n". 98 98 " --user <username> Username to use for authentication\n". … … 215 215 $physical_memory = `sysctl -n hw.memsize` or memerror; 216 216 $swap_memory = `sysctl -n vm.swapusage | awk '{print \$3}' | sed 's/\..*\$//'` or memerror; 217 } elsif ($os =~ /NetBSD /) {217 } elsif ($os =~ /NetBSD|OpenBSD/) { 218 218 $physical_memory = `sysctl -n hw.physmem` or memerror; 219 219 $swap_memory = `swapctl -l | grep '^/' | awk '{ s+= \$2 } END { print s }'` or memerror; … … 237 237 exit; 238 238 } 239 # Are we being asked to connect via a socket? 240 if ($opt{socket} ne 0) { 241 $remotestring = " -S $opt{socket}"; 242 } 239 243 # Are we being asked to connect to a remote server? 240 244 if ($opt{host} ne 0) { … … 277 281 $mysqllogin = ""; 278 282 # Did this go well because of a .my.cnf file or is there no password set? 279 my $userpath = `ls -d ~`; 280 chomp($userpath); 281 unless ( -e "$userpath/.my.cnf" ) { 283 my $userpath = `ls -d ~ 2>/dev/null`; 284 if (length($userpath) > 0) { 285 chomp($userpath); 286 } 287 unless ( -e "${userpath}/.my.cnf" ) { 282 288 badprint "Successfully authenticated with no password - SECURITY RISK!\n"; 283 289 } … … 410 416 if ($mysqlvermajor >= 5) { 411 417 # MySQL 5 servers can have table sizes calculated quickly from information schema 412 my @templist = `mysql $mysqllogin -Bse "SELECT ENGINE,SUM(DATA_LENGTH),COUNT(ENGINE) FROM information_schema.TABLES WHERE TABLE_SCHEMA NOT IN ('information_schema','mysql') GROUP BY ENGINE HAVING SUM(DATA_LENGTH) > 0ORDER BY ENGINE ASC;"`;418 my @templist = `mysql $mysqllogin -Bse "SELECT ENGINE,SUM(DATA_LENGTH),COUNT(ENGINE) FROM information_schema.TABLES WHERE TABLE_SCHEMA NOT IN ('information_schema','mysql') GROUP BY ENGINE ORDER BY ENGINE ASC;"`; 413 419 foreach my $line (@templist) { 414 420 my ($engine,$size,$count); … … 464 470 push(@generalrec,"Add skip-innodb to MySQL configuration to disable InnoDB"); 465 471 } 466 if (!defined $enginestats{'B DB'} && defined $myvar{'have_bdb'} && $myvar{'have_bdb'} eq "YES") {472 if (!defined $enginestats{'BerkeleyDB'} && defined $myvar{'have_bdb'} && $myvar{'have_bdb'} eq "YES") { 467 473 badprint "BDB is enabled but isn't being used\n"; 468 474 push(@generalrec,"Add skip-bdb to MySQL configuration to disable BDB"); … … 523 529 $mycalc{'pct_keys_from_mem'} = sprintf("%.1f",(100 - (($mystat{'Key_reads'} / $mystat{'Key_read_requests'}) * 100))); 524 530 } 525 if ($doremote eq 0 ) {526 $mycalc{'total_myisam_indexes'} = `find $myvar{'datadir'} -name '*.MYI' 2>&1 | xargs du -L $duflags '{}' 2>&1 | awk '{ s += \$1 } END { print s}'`;527 } elsif ($ doremote eq 1 and $mysqlvermajor >= 5) {528 $mycalc{'total_myisam_indexes'} = `mysql $mysqllogin -Bse "SELECT SUM(INDEX_LENGTH) FROM information_schema.TABLES WHERE TABLE_SCHEMA NOT IN ('information_schema');"`;531 if ($doremote eq 0 and $mysqlvermajor < 5) { 532 $mycalc{'total_myisam_indexes'} = `find $myvar{'datadir'} -name '*.MYI' 2>&1 | xargs du -L $duflags '{}' 2>&1 | awk '{ s += \$1 } END { printf (\"%d\",s) }'`; 533 } elsif ($mysqlvermajor >= 5) { 534 $mycalc{'total_myisam_indexes'} = `mysql $mysqllogin -Bse "SELECT IFNULL(SUM(INDEX_LENGTH),0) FROM information_schema.TABLES WHERE TABLE_SCHEMA NOT IN ('information_schema');"`; 529 535 } 530 536 if (defined $mycalc{'total_myisam_indexes'} and $mycalc{'total_myisam_indexes'} =~ /^0\n$/) { … … 624 630 625 631 # Memory usage 626 infoprint "Total buffers: ".hr_bytes($mycalc{' per_thread_buffers'})." per thread and ".hr_bytes($mycalc{'server_buffers'})." global\n";632 infoprint "Total buffers: ".hr_bytes($mycalc{'server_buffers'})." global + ".hr_bytes($mycalc{'per_thread_buffers'})." per thread ($myvar{'max_connections'} max threads)\n"; 627 633 if ($mycalc{'total_possible_used_memory'} > 2*1024*1024*1024 && $arch eq 32) { 628 634 badprint "Allocating > 2GB RAM on 32-bit systems can cause system instability\n"; … … 672 678 if ($mystat{'Key_read_requests'} > 0) { 673 679 if ($mycalc{'pct_keys_from_mem'} < 95) { 674 badprint "Key buffer hit rate: $mycalc{'pct_keys_from_mem'}% \n";680 badprint "Key buffer hit rate: $mycalc{'pct_keys_from_mem'}% (".hr_num($mystat{'Key_read_requests'})." cached / ".hr_num($mystat{'Key_reads'})." reads)\n"; 675 681 } else { 676 goodprint "Key buffer hit rate: $mycalc{'pct_keys_from_mem'}% \n";682 goodprint "Key buffer hit rate: $mycalc{'pct_keys_from_mem'}% (".hr_num($mystat{'Key_read_requests'})." cached / ".hr_num($mystat{'Key_reads'})." reads)\n"; 677 683 } 678 684 } else { … … 694 700 } else { 695 701 if ($mycalc{'query_cache_efficiency'} < 20) { 696 badprint "Query cache efficiency: $mycalc{'query_cache_efficiency'}% \n";702 badprint "Query cache efficiency: $mycalc{'query_cache_efficiency'}% (".hr_num($mystat{'Qcache_hits'})." cached / ".hr_num($mystat{'Qcache_hits'}+$mystat{'Com_select'})." selects)\n"; 697 703 push(@adjvars,"query_cache_limit (> ".hr_bytes_rnd($myvar{'query_cache_limit'}).", or use smaller result sets)"); 698 704 } else { 699 goodprint "Query cache efficiency: $mycalc{'query_cache_efficiency'}% \n";705 goodprint "Query cache efficiency: $mycalc{'query_cache_efficiency'}% (".hr_num($mystat{'Qcache_hits'})." cached / ".hr_num($mystat{'Qcache_hits'}+$mystat{'Com_select'})." selects)\n"; 700 706 } 701 707 if ($mycalc{'query_cache_prunes_per_day'} > 98) { … … 712 718 # No sorts have run yet 713 719 } elsif ($mycalc{'pct_temp_sort_table'} > 10) { 714 badprint "Sorts requiring temporary tables: $mycalc{'pct_temp_sort_table'}% \n";720 badprint "Sorts requiring temporary tables: $mycalc{'pct_temp_sort_table'}% (".hr_num($mystat{'Sort_merge_passes'})." temp sorts / ".hr_num($mycalc{'total_sorts'})." sorts)\n"; 715 721 push(@adjvars,"sort_buffer_size (> ".hr_bytes_rnd($myvar{'sort_buffer_size'}).")"); 716 722 push(@adjvars,"read_rnd_buffer_size (> ".hr_bytes_rnd($myvar{'read_rnd_buffer_size'}).")"); 717 723 } else { 718 goodprint "Sorts requiring temporary tables: $mycalc{'pct_temp_sort_table'}% \n";724 goodprint "Sorts requiring temporary tables: $mycalc{'pct_temp_sort_table'}% (".hr_num($mystat{'Sort_merge_passes'})." temp sorts / ".hr_num($mycalc{'total_sorts'})." sorts)\n"; 719 725 } 720 726 … … 732 738 if ($mystat{'Created_tmp_tables'} > 0) { 733 739 if ($mycalc{'pct_temp_disk'} > 25 && $mycalc{'max_tmp_table_size'} < 256*1024*1024) { 734 badprint "Temporary tables created on disk: $mycalc{'pct_temp_disk'}% \n";740 badprint "Temporary tables created on disk: $mycalc{'pct_temp_disk'}% (".hr_num($mystat{'Created_tmp_disk_tables'})." on disk / ".hr_num($mystat{'Created_tmp_disk_tables'} + $mystat{'Created_tmp_tables'})." total)\n"; 735 741 push(@adjvars,"tmp_table_size (> ".hr_bytes_rnd($myvar{'tmp_table_size'}).")"); 736 742 push(@adjvars,"max_heap_table_size (> ".hr_bytes_rnd($myvar{'max_heap_table_size'}).")"); … … 738 744 push(@generalrec,"Reduce your SELECT DISTINCT queries without LIMIT clauses"); 739 745 } elsif ($mycalc{'pct_temp_disk'} > 25 && $mycalc{'max_tmp_table_size'} >= 256) { 740 badprint "Temporary tables created on disk: $mycalc{'pct_temp_disk'}% \n";746 badprint "Temporary tables created on disk: $mycalc{'pct_temp_disk'}% (".hr_num($mystat{'Created_tmp_disk_tables'})." on disk / ".hr_num($mystat{'Created_tmp_disk_tables'} + $mystat{'Created_tmp_tables'})." total)\n"; 741 747 push(@generalrec,"Temporary table size is already large - reduce result set size"); 742 748 push(@generalrec,"Reduce your SELECT DISTINCT queries without LIMIT clauses"); 743 749 } else { 744 goodprint "Temporary tables created on disk: $mycalc{'pct_temp_disk'}% \n";750 goodprint "Temporary tables created on disk: $mycalc{'pct_temp_disk'}% (".hr_num($mystat{'Created_tmp_disk_tables'})." on disk / ".hr_num($mystat{'Created_tmp_disk_tables'} + $mystat{'Created_tmp_tables'})." total)\n"; 745 751 } 746 752 } else { … … 756 762 } else { 757 763 if ($mycalc{'thread_cache_hit_rate'} <= 50) { 758 badprint "Thread cache hit rate: $mycalc{'thread_cache_hit_rate'}% \n";764 badprint "Thread cache hit rate: $mycalc{'thread_cache_hit_rate'}% (".hr_num($mystat{'Threads_created'})." created / ".hr_num($mystat{'Connections'})." connections)\n"; 759 765 push(@adjvars,"thread_cache_size (> $myvar{'thread_cache_size'})"); 760 766 } else { 761 goodprint "Thread cache hit rate: $mycalc{'thread_cache_hit_rate'}% \n";767 goodprint "Thread cache hit rate: $mycalc{'thread_cache_hit_rate'}% (".hr_num($mystat{'Threads_created'})." created / ".hr_num($mystat{'Connections'})." connections)\n"; 762 768 } 763 769 } … … 766 772 if ($mystat{'Open_tables'} > 0) { 767 773 if ($mycalc{'table_cache_hit_rate'} < 20) { 768 badprint "Table cache hit rate: $mycalc{'table_cache_hit_rate'}% \n";774 badprint "Table cache hit rate: $mycalc{'table_cache_hit_rate'}% (".hr_num($mystat{'Open_tables'})." open / ".hr_num($mystat{'Opened_tables'})." opened)\n"; 769 775 if ($mysqlvermajor eq 6) { 770 776 push(@adjvars,"table_cache (> ".$myvar{'table_open_cache'}.")"); … … 774 780 push(@generalrec,"Increase table_cache gradually to avoid file descriptor limits"); 775 781 } else { 776 goodprint "Table cache hit rate: $mycalc{'table_cache_hit_rate'}% \n";782 goodprint "Table cache hit rate: $mycalc{'table_cache_hit_rate'}% (".hr_num($mystat{'Open_tables'})." open / ".hr_num($mystat{'Opened_tables'})." opened)\n"; 777 783 } 778 784 } … … 781 787 if (defined $mycalc{'pct_files_open'}) { 782 788 if ($mycalc{'pct_files_open'} > 85) { 783 badprint "Open file limit used: $mycalc{'pct_files_open'}% \n";789 badprint "Open file limit used: $mycalc{'pct_files_open'}% (".hr_num($mystat{'Open_files'})."/".hr_num($myvar{'open_files_limit'}).")\n"; 784 790 push(@adjvars,"open_files_limit (> ".$myvar{'open_files_limit'}.")"); 785 791 } else { 786 goodprint "Open file limit used: $mycalc{'pct_files_open'}% \n";792 goodprint "Open file limit used: $mycalc{'pct_files_open'}% (".hr_num($mystat{'Open_files'})."/".hr_num($myvar{'open_files_limit'}).")\n"; 787 793 } 788 794 } … … 794 800 push(@generalrec,"Optimize queries and/or use InnoDB to reduce lock wait"); 795 801 } else { 796 goodprint "Table locks acquired immediately: $mycalc{'pct_table_locks_immediate'}% \n";802 goodprint "Table locks acquired immediately: $mycalc{'pct_table_locks_immediate'}% (".hr_num($mystat{'Table_locks_immediate'})." immediate / ".hr_num($mystat{'Table_locks_waited'}+$mystat{'Table_locks_immediate'})." locks)\n"; 797 803 } 798 804 }