十二、优化SQL
扬SQL之长,其它事情交由应用去做。
使用SQL服务器来做:
找出基于WHERE子句的行。
JOIN表
GROUP BY
ORDER BY
DISTINCT
不要使用SQL来做:
检验数据(如日期)
成为一只计算器
技巧:
明智地使用键码。
键码适合搜索,但不适合索引列的插入/更新。
保持数据为数据库第三范式,但不要担心冗余信息或这如果你需要更快的速度,创建总结表。
在大表上不做GROUP BY,相反创建大表的总结表并查询它。
UPDATE table set count=count+1 where key_column=constant非常快。
对于大表,或许最好偶尔生成总结表而不是一直保持总结表。
充分利用INSERT的默认值。
十三、不同SQL服务器的速度差别(以秒计)
通过键码读取2000000行: NT Linux
mysql 367 249
mysql_odbc 464
db2_odbc 1206
informix_odbc 121126
ms-sql_odbc 1634
oracle_odbc 20800
solid_odbc 877
sybase_odbc 17614
插入350768行: NT Linux
mysql 381 206
mysql_odbc 619
db2_odbc 3460
informix_odbc 2692
ms-sql_odbc 4012
oracle_odbc 11291
solid_odbc 1801
sybase_odbc 4802
在上述测试中,MySQL配置8M高速缓存运行,其他数据库以默认安装运行。
二十九、MySQL各种锁定
内部表锁定
LOCK TABLES(所有表类型适用)
GET LOCK()/RELEASE LOCK()
页面锁定(对BDB表)
ALTER TABLE也在BDB表上进行表锁定
LOCK TABLES允许一个表有多个读者和一个写者。
一般WHERE锁定具有比READ锁定高的优先级以避免让写入方干等。 对于不重要的写
入方,可以使用LOW_PRIORITY关键字让锁定处理器优选读取方。
UPDATE LOW_PRIORITY SET =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() from trans where customer_id=some_id;
mysql> update customer set total_=sum_from_previous_statement
where customer_id=some_id;
mysql> UNLOCK TABLES;
BDB表如何进行事务:
mysql> BEGIN WORK;
mysql> select sum() from trans where customer_id=some_id;
mysql> update customer set total_=sum_from_previous_statement
where customer_id=some_id;
mysql> COMMIT;
注意你可以通过下列语句回避事务:
UPDATE customer SET =+new_ 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 S (...)
UNLOCK TABLES t1;
ENDIF
而用
REPLACE INTO t1 S (...)
三十三、一般技巧
使用短主键。联结表时使用数字而非字符串。
当使用多部分键码时,第一部分应该时最常用的部分。
有疑问时,首先使用更多重复的列以获得更好地键码压缩。
如果在同一台机器上运行MySQL客户和服务器,那么在连接MySQL时则使用套接字而不是
TCP/IP(这可以提高性能7.5%)。可在连接MySQL服务器时不指定主机名或主机名为localhost
来做到。
如果可能,使用--skip-locking(在某些OS上为默认),这将关闭外部锁定并将提高性能。
使用应用层哈希值而非长键码:
SELECT * FROM table_name WHERE hash=MD5(concat(col1,col2)) AND
col_1=constant AND col_2=constant