a. select count(*) from world.city where>
b. select (select count(*) from world.city) – count(*) from world.city where> a语句当行数超过11行的时候需要扫描的行数比b语句要多, b语句扫描了6行,
此种情况下,b语句比a语句更有效率。
当没有where语句的时候直接select count(*) from world.city这样会更快,
因为mysql总是知道表的行数。
2. 避免使用不兼容的数据类型。
例如float和int、char和varchar、binary和varbinary是不兼容的。数据类型的不兼容可能使优化器无法执行一些本来可以进行的优化操作。 在程序中,保证在实现功能的基础上,尽量减少对数据库的访问次数;通过搜索参数,尽量减少对表的访问行数,最小化结果集,从而减轻网络负担;能够分开的操作尽量分开处理,提高每次的响应速度;
在数据窗口使用SQL时,尽量把使用的索引放在选择的首列;算法的结构尽量简单;在查询时,不要过多地使用通配符如 SELECT * FROM T1语句,
要用到几列就选择几列如:SELECT COL1,COL2 FROM T1;
在可能的情况下尽量限制尽量结果集行数如:SELECT TOP 300 COL1,COL2,COL3 FROM T1,因为某些情况下用户是不需要那么多的数据的。不要在应用中使用数据库游标,游标是非常有用的工具,但比使用常规的、面向集的SQL语句需要更大的开销;按照特定顺序提取数据的查找。
3. 索引字段上进行运算会使索引失效。
尽量避免在WHERE子句中对字段进行函数或表达式操作,这将导致引擎放弃使用索引而进行全表扫描。
如: SELECT * FROM T1 WHERE F1/2=100 应改为: SELECT * FROM T1 WHERE F1=100*2
4. 避免使用!=或<>、IS NULL或IS NOT NULL、IN ,NOT IN等这样的操作符.
SELECT SUM(T1.C1) FROM T1 WHERE (SELECT COUNT(*)FROM T2 WHERE T2.C2=T1.C2>0)
2.SELECT SUM(T1.C1) FROM T1WHERE EXISTS(SELECT * FROM T2 WHERE T2.C2=T1.C2) 两者产生相同的结果,但是后者的效率显然要高于前者。因为后者不会产生大量锁定的表扫描或是索引扫描。
如果你想校验表里是否存在某条纪录,不要用count(*)那样效率很低,而且浪费服务器资源。可以用EXISTS代替。如: IF (SELECT COUNT(*) FROM table_name WHERE column_name = ‘xxx’)可以写成:IF EXISTS (SELECT * FROM table_name WHERE column_name = ‘xxx’)
7. 能够用BETWEEN的就不要用IN 8. 能够用DISTINCT的就不用GROUP BY 9. 尽量不要用SELECT INTO语句。SELECT INTO 语句会导致表锁定,阻止其他用户访问该表。 10. 必要时强制查询优化器使用某个索引
SELECT * FROM T1 WHERE nextprocess = 1 AND processid IN (8,32,45) 改成: SELECT * FROM T1 (INDEX = IX_ProcessID) WHERE nextprocess = 1 AND processid IN (8,32,45) 则查询优化器将会强行利用索引IX_ProcessID 执行查询。
11. 消除对大型表行数据的顺序存取
尽管在所有的检查列上都有索引,但某些形式的WHERE子句强迫优化器使用顺序存取。如: SELECT * FROM orders WHERE (customer_num=104 AND order_num>1001) OR order_num=1008 解决办法可以使用并集来避免顺序存取: SELECT * FROM orders WHERE customer_num=104 AND order_num>1001 UNION SELECT * FROM orders WHERE order_num=1008 这样就能利用索引路径处理查询。【jacking 数据结果集很多,但查询条件限定后结果集不大的情况下,后面的语句快】
12. 尽量避免在索引过的字符数据中,使用非打头字母搜索。这也使得引擎无法利用索引。
见如下例子: SELECT * FROM T1 WHERE NAME LIKE ‘%L%’ SELECT * FROM T1 WHERE SUBSTING(NAME,2,1)=’L’ SELECT * FROM T1 WHERE NAME LIKE ‘L%’ 即使NAME字段建有索引,前两个查询依然无法利用索引完成加快操作,引擎不得不对全表所有数据逐条操作来完成任务。而第三个查询能够使用索引来加快操作,不要习惯性的使用 ‘%L%’这种方式(会导致全表扫描),如果可以使用`L%’相对来说更好;
13. 虽然UPDATE、DELETE语句的写法基本固定,但是还是对UPDATE语句给点建议:
a) 尽量不要修改主键字段。 b) 当修改VARCHAR型字段时,尽量使用相同长度内容的值代替。 c) 尽量最小化对于含有UPDATE触发器的表的UPDATE操作。 d) 避免UPDATE将要复制到其他数据库的列。 e) 避免UPDATE建有很多索引的列。 f) 避免UPDATE在WHERE子句条件中的列。
14. 能用UNION ALL就不要用UNION
UNION ALL不执行SELECT DISTINCT函数,这样就会减少很多不必要的资源 在跨多个不同的数据库时使用UNION是一个有趣的优化方法,UNION从两个互不关联的表中返回数据,这就意味着不会出现重复的行,同时也必须对数据进行排序,我们知道排序是非常耗费资源的,特别是对大表的排序。 UNION ALL可以大大加快速度,如果你已经知道你的数据不会包括重复行,或者你不在乎是否会出现重复的行,在这两种情况下使用UNION ALL更适合。此外,还可以在应用程序逻辑中采用某些方法避免出现重复的行,这样UNION ALL和UNION返回的结果都是一样的,但UNION ALL不会进行排序。
15. 字段数据类型优化:
a. 避免使用NULL类型:NULL对于大多数数据库都需要特殊处理,MySQL也不例外,它需要更多的代码,更多的检查和特殊的索引逻辑,有些开发人员完全没有意识到,创建表时NULL是默认值,但大多数时候应该使用NOT NULL,或者使用一个特殊的值,如0,-1作为默认值。 b. 尽可能使用更小的字段,MySQL从磁盘读取数据后是存储到内存中的,然后使用cpu周期和磁盘I/O读取它,这意味着越小的数据类型占用的空间越小,从磁盘读或打包到内存的效率都更好,但也不要太过执着减小数据类型,要是以后应用程序发生什么变化就没有空间了。修改表将需要重构,间接地可能引起代码的改变,这是很头疼的问题,因此需要找到一个平衡点。 c. 优先使用定长型
16. 关于大数据量limit分布的优化见下面链接(当偏移量特别大时,limit效率会非常低):
http://ariyue.iteye.com/blog/553541 附上一个提高limit效率的简单技巧,在覆盖索引(覆盖索引用通俗的话讲就是在select的时候只用去读取索引而取得数据,无需进行二次select相关表)上进行偏移,而不是对全行数据进行偏移。可以将从覆盖索引上提取出来的数据和全行数据进行联接,然后取得需要的列,会更有效率,看看下面的查询: mysql> select film_id, description from sakila.film order by>
17. 程序中如果一次性对同一个表插入多条数据,比如以下语句:
insert into person(name,age) values(‘xboy’, 14); insert into person(name,age) values(‘xgirl’, 15); insert into person(name,age) values(‘nia’, 19); 把它拼成一条语句执行效率会更高. insert into person(name,age) values(‘xboy’, 14), (‘xgirl’, 15),(‘nia’, 19);