Cover | Table of Contents | Colophon
checking and savings. To move $200 from Jane's checking
account to her savings account, you need to perform at least three
steps:START
TRANSACTION statement and then either make its changes
permanent with COMMIT or discard the
changes with ROLLBACK. So, the SQL
for our sample transaction might look like this:1 START TRANSACTION; 2 SELECT balance FROM checking WHERE customer_id = 10233276; 3 UPDATE checking SET balance = balance - 200.00 WHERE customer_id = 10233276; 4 UPDATE savings SET balance = balance + 200.00 WHERE customer_id = 10233276; 5 COMMIT;
REPEATABLE
READMyTable, MySQL stores the table definition in
MyTable.frm. Because MySQL uses the filesystem to
store database names and table definitions, case sensitivity depends on
the platform. On a Windows MySQL instance, table and database names are
case insensitive; on Unix-like systems, they are case sensitive. Each
storage engine stores the table's data and indexes differently, but the
server itself handles the table definition.SHOW TABLE STATUS command. For
example, to examine the user table in
the mysql database, execute the
following:mysql> SHOW TABLE STATUS LIKE 'user' \G
*************************** 1. row ***************************
Name: user
Engine: MyISAM
Row_format: Dynamic
Rows: 6
Avg_row_length: 59
Data_length: 356
Max_data_length: 4294967295
Index_length: 2048
Data_free: 0
Auto_increment: NULL
Create_time: 2002-01-24 18:07:17
Update_time: 2002-01-24 21:56:29
Check_time: NULL
Collation: utf8_bin
Checksum: NULL
Create_options:
Comment: Users and global privileges
1 row in set (0.00 sec)http://www.mysqlperformanceblog.com/ http://www.mysqlperformanceblog.com/page/2/ http://www.mysqlperformanceblog.com/mysql-patches/ http://www.mysqlperformanceblog.com/mysql-performance-presentations/ http://www.mysqlperformanceblog.com/2006/09/06/slow-query-log-analyzes-tools/
$ http_load -parallel 1 -seconds 10 urls.txt
19 fetches, 1 max parallel, 837929 bytes, in 10.0003 seconds
44101.5 mean bytes/connection
1.89995 fetches/sec, 83790.7 bytes/sec
msecs/connect: 41.6647 mean, 56.156 max, 38.21 min
msecs/first-response: 320.207 mean, 508.958 max, 179.308 min
HTTP response codes:
code 200 - 19
$ http_load -parallel 5 -seconds 10 urls.txt
94 fetches, 5 max parallel, 4.75565e+06 bytes, in 10.0005 seconds
50592 mean bytes/connection
9.39953 fetches/sec, 475541 bytes/sec
msecs/connect: 65.1983 mean, 169.991 max, 38.189 min
msecs/first-response: 245.014 mean, 993.059 max, 99.646 min
HTTP response codes:
code 200 - 94
$ http_load -rate 5 -seconds 10 urls.txt
48 fetches, 4 max parallel, 2.50104e+06 bytes, in 10 seconds
52105 mean bytes/connection
4.8 fetches/sec, 250104 bytes/sec
msecs/connect: 42.5931 mean, 60.462 max, 38.117 min
msecs/first-response: 246.811 mean, 546.203 max, 108.363 min
HTTP response codes:
code 200 - 48SHOW
PROCESSLIST in MySQL, and note the Host column in one of the processes. We use
the following example:*************************** 21. row ***************************
Id: 91296
User: web
Host: sargon.cluster3:37636
db: main
Command: Sleep
Time: 10
State:
Info: NULL
Host column shows where
the connection originated and, just as importantly, the TCP port from
which it came. You can use that information to find out which process opened the connection. If you
have root access to sargon, you can use netstat
and the port number to find out which process opened the
connection:root@sargon#
NULL if
possible.NOT
NULL whenever you can. A lot of tables include
nullable columns even when the application does not
need to store mysql> SELECT first_name FROM sakila.actor WHERE actor_id = 5;
actor_id column, so MySQL will use the index
to find rows whose actor_id is
5. In other words, it performs a
lookup on the values in the index and returns any rows containing the
specified value.actor_id:mysql> SELECT actor_id FROM sakila.actor WHERE actor_id + 1 = 5;
WHERE clause is equivalent to actor_id = 4, but MySQL can't solve the
equation for actor_id. It's up to
you to do this. You should get in the habit of simplifying your
WHERE criteria, so the indexed
column is alone on one side of the comparison operator.mysql> SELECT ... WHERE TO_DAYS(CURRENT_DATE) - TO_DAYS(date_col) <= 10;
date_col value is newer than 10 days ago,
but it won't use indexes because of the TO_DAYS() function. Here's a better way to
write this query:mysql> SELECT ... WHERE date_col >= DATE_SUB(CURRENT_DATE, INTERVAL 10 DAY);
CURRENT_DATE will prevent the query cache
from caching the results. You can replace CURRENT_DATE with a literal to fix that
problem:WHERE clause such as WHERE age BETWEEN 18 AND 25 if the same query
uses an index to sort users by the ratings other users have given them.
If MySQL uses an index for a range criterion in a query, it cannot also
use another index (or a suffix of the same index) for ordering. Assuming
this will be one of the most common WHERE clauses, we'll take for granted that
many queries will need a filesort.WHERE
clauses most often. Indexes on columns with many distinct values will
be very selective. This is generally a good thing, because it lets
MySQL filter out undesired rows more efficiently.country column may or may
not be selective, but it'll probably be in most queries anyway. The
sex column is certainly not
selective, but it'll probably be in every query. With this in mind, we
create a series of indexes for many different combinations of columns,
prefixed with (sex,country).CHECK TABLE to see if the table is corrupt.
(Note that some storage engines don't support this command, and others
support multiple options to specify how thoroughly they check the
table.) CHECK TABLE usually catches
most table and index errors.REPAIR TABLE command, but again, not all
storage engines support this. In these cases you can do a "no-op"
ALTER, such as altering a table to
use the same storage engine it currently uses. Here's an example for
an InnoDB table:mysql> ALTER TABLE innodb_tbl ENGINE=INNODB;
EMPLOYEE | DEPARTMENT | HEAD |
|---|---|---|
Jones | Accounting | Jones |
Smith | Engineering | Smith |
Brown | Accounting | Jones |
Green | Engineering | Smith |
EMPLOYEE_NAME | DEPARTMENT |
|---|---|
Jones | Accounting |
Smith | Engineering |
Brown | Accounting |
Green | Engineering |
DEPARTMENT | HEAD |
|---|---|
Accounting |
ALTER TABLE performance
can become a problem with very large tables. MySQL performs most
alterations by making an empty table with the desired new structure,
inserting all the data from the old table into the new one, and deleting
the old table. This can take a very long time, especially if you're
short on memory and the table is large and has lots of indexes. Many people have experience with ALTER TABLE operations that have taken hours
or days to complete.ALTER TABLE operations
cause table rebuilds. For example, you can change or drop a column's
default value in two ways (one fast, and one slow). Say you want to
change a film's default rental duration from 3 to 5 days. Here's the
expensive way:mysql> ALTER TABLE sakila.film -> MODIFY COLUMN rental_duration TINYINT(3) NOT NULL DEFAULT 5;
SHOW
STATUS shows that it does 1,000 handler reads and 1,000
inserts. In other words, it copied the table to a new table, even though
the column's type, size, and nullability didn't change.MODIFY
COLUMN will cause a table rebuild.UPDATE, for example, some
of the rows will be updated and some won't.