+-------+--------+---------------+---------+---------+------------------+------+---------------------------------+
| t1 | ALL | NULL | NULL | NULL | NULL | 11 | Using temporary; Using filesort |
| t2 | ref | ID | ID | 4 | t1.TransactionID | 13 | |
| t3 | eq_ref | PRIMARY | PRIMARY | 4 | t2.GroupID | 1 | |
+-------+--------+---------------+---------+---------+------------------+------+---------------------------------+
ALL和范围类型提示一个潜在的问题。
--------------------------------------------------------------------------------
二十五、学会使用SHOW PROCESSLIST
使用SHOW processlist来发现正在做什么:
+----+-------+-----------+----+---------+------+--------------+-------------------------------------+
| Id | User | Host | db | Command | Time | State | Info |
+----+-------+-----------+----+---------+------+--------------+-------------------------------------+
| 6 | monty | localhost | bp | Query | 15 | Sending data | select * from station,station as s1 |
| 8 | monty | localhost | | Query | 0 | | show processlist |
+----+-------+-----------+----+---------+------+--------------+-------------------------------------+
在mysql或mysqladmin中用KILL来杀死溜掉的线程。
--------------------------------------------------------------------------------
二十六、如何知晓MySQL解决一条查询
运行项列命令并试图弄明白其输出:
SHOW VARIABLES;
SHOW COLUMNS FROM ...G
EXPLAIN SELECT ...G
FLUSH STATUS;
SELECT ...;
SHOW STATUS;
--------------------------------------------------------------------------------
二十七、MySQL非常不错
日志
在进行很多连接时,连接非常快。
同时使用SELECT和 INSERT的场合。
在不把更新与耗时太长的选择结合时。
在大多数选择/更新使用唯一键码时。
在使用没有长时间冲突锁定的 多个表时。
在用大表时(MySQL使用一个非常紧凑的表格式)。
--------------------------------------------------------------------------------
二十八、MySQL应避免的事情
用删掉的行更新或插入表,结合要耗时长的SELECT。
在能放在 WHERE子句中的列上用HAVING。
不使用键码或键码不够唯一而进行JOIN。
在不同列类型的列上JOIN。
在不使 用=匹配整个键码时使用HEAP表。
在MySQL监控程序中忘记在UPDATE或DELETE中使用一条WHERE子句。如果想这样做,使用 mysql客户程序的--i-am-a-dummy选项。
--------------------------------------------------------------------------------
二十九、MySQL各种锁定
内部表锁定
LOCK TABLES(所有表类型适用)
GET LOCK()/RELEASE LOCK()
页面锁定(对BDB表)
ALTER TABLE也在BDB表上进行表锁定
LOCK TABLES允许一个表有多个读者和一个写者。
一般WHERE锁定具有比READ锁定高的优先级以避免让写入方干等。对于不重要的写入方,可 以使用LOW_PRIORITY关键字让锁定处理器优选读取方。
UPDATE LOW_PRIORITY SET value=10 WHERE id=10;
--------------------------------------------------------------------------------
三十、给MySQL更多信息以更好地解决问题的技巧
注意你总能去掉(加注释)MySQL功能以使查询可移植:
SELECT /*! SQL_BUFFER_RESULTS */ ...
SELECT SQL_BUFFER_RESULTS ...
将强制 MySQL生成一个临时结果集。只要所有临时结果集生成后,所有表上的锁定均被释放。这能在遇到表锁定问题时或要花很长时间将结果传给客户端时有所帮助。
SELECT SQL_SMALL_RESULT ... GROUP BY ...
告诉优化器结果集将只包含很少的行。
SELECT SQL_BIG_RESULT ... GROUP BY ...
告诉优化器结果集将包含很多行。
SELECT STRAIGHT_JOIN ...
强制优化器以出现在FROM子句中的次序联结表。
SELECT ... FROM table_name [USE INDEX (index_list) | IGNORE INDEX (index_list)] table_name2
强制MySQL使用/忽略列出的索引。
--------------------------------------------------------------------------------
三十一、事务的例子
MyIASM表如何进行事务处理:
mysql> LOCK TABLES trans READ, customer WRITE;
mysql> select sum(value) from trans where customer_id=some_id;
mysql> update customer set total_value=sum_from_previous_statement
where customer_id=some_id;
mysql> UNLOCK TABLES;
BDB表如何进行事务:
mysql> BEGIN WORK;
mysql> select sum(value) from trans where customer_id=some_id;
mysql> update customer set total_value=sum_from_previous_statement
where customer_id=some_id;
mysql> COMMIT;
注意你可以通过下列语句回避事务:
UPDATE customer SET value=value+new_value WHERE customer_id=some_id;
--------------------------------------------------------------------------------
三十二、使用REPLACE的例子
REPLACE的功能极像INSERT,除了如果一条老记录在一个唯一索引上具有 与新纪录相同的值,那么老记录在新纪录插入前则被删除。不使用
SELECT 1 FROM t1 WHERE key=#
IF found-row
LOCK TABLES t1
DELETE FROM t1 WHERE key1=#
INSERT INTO t1 VALUES (...)
UNLOCK TABLES t1;
ENDIF
而用
REPLACE INTO t1 VALUES (...)
--------------------------------------------------------------------------------
三十三、一般技巧
使用短主键。联结表时使用数字而非字符串。
当使用多部分键码时,第一部分应该时最常用的 部分。
有疑问时,首先使用更多重复的列以获得更好地键码压缩。
如果在同一台机器上运行MySQL客户和服务器,那么在连接MySQL 时则使用套接字而不是TCP/IP(这可以提高性能7.5%)。可在连接MySQL服务器时不指定主机名或主机名为localhost来做到。
如 果可能,使用--skip-locking(在某些OS上为默认),这将关闭外部锁定并将提高性能。