SQL优化

 1). 应尽量避免在 where 子句中对字段进行 null 值判断

       否则将导致引擎放弃使用索引而进行全表扫描,如:

       select id from twhere num is null

       NULL对于大多数数据库都需要特殊处理,MySQL也不例外,它需要更多的代码,更多的检查和特殊的索引逻辑,有些开发人员完全没有意识到,创建表时NULL是默认值,但大多数时候应该使用NOTNULL,或者使用一个特殊的值,如0-1作为默  认值。

       不能用null作索引,任何包含null值的列都将不会被包含在索引中。即使索引有多列这样的情况下,只要这些列中有一列含有null,该列   就会从索引中排除。也就是说如果某列存在空值,即使对该列建索引也不会提高性能。任何在where子句中使用is nullis notnull的语句优化器是不允许使用索引的。

       此例可以在num上设置默认值0,确保表中num列没有null值,然后这样查询:

        selectid    from t where num=0

 2).应尽量避免在 where 子句中使用!=<>操作符

        否则将引擎放弃使用索引而进行全表扫描。
         MySQL
只有对以下操作符才使用索引:<<==>>=BETWEENIN,以及某些时候的LIKE 

        可以在LIKE操作中使用索引的情形是指另一个操作数不是以通配符(%或者_)开头的情形。例如:
      
  SELECT id FROM  t WHERE col LIKE 'Mich%'; #  这个查询将使用索引,
         SELECT idFROM  t WHERE col  LIKE '%ike';   #
这个查询不会使用索引。

 3).应尽量避免在 where 子句中使用 or 来连接条件

       否则将导致引擎放弃使用索引而进行全表扫描,如:

       select id from twhere num=10 or num=20

       可以 使用UNION合并查询: selectid from t where num=10 union all select id from t where num=20

          

      在某些情况下,or条件可以避免全表扫描的。

       1 .where 语句里面如果带有or条件, myisam表能用到索引, innodb不行。

           2 .必须所有的or条件都必须是独立索引

       mysql or条件可以使用索引而避免全表

 

 4).in not in 也要慎用,否则会导致全表扫描,

       如:

       select id from twhere num in(1,2,3)

       对于连续的数值,能用between 就不要用in 了:

       Select id from twhere num between 1 and 3

 5).下面的查询也将导致全表扫描:

       select id from t where name like '%abc%' 或者

       select id from t where name like '%abc' 或者

       若要提高效率,可以考虑全文检索。

       selectid from t where name like 'abc%' 才用到索引

 7).如果在 where 子句中使用参数,也会导致全表扫描。

      因为SQL只有在运行时才会解析局部变量,但优化程序不能将访问计划的选择推迟到运行时;它必须在编译时进行选择。然而,如果在编译时建立访问计划,变量的值还是未知的,因而无法作为索引选择的输入项。如下面语句将进行全表扫描:

      select id from t where num=@num

      可以改为强制查询使用索引:select id from t with(index(索引名))where num=@num

 8).应尽量避免在 where 子句中对字段进行表达式操作,

      这将导致引擎放弃使用索引而进行全表扫描。如:

      select id from t wherenum/2=100

      应改为: select id from t where num=100*2

9). 应尽量避免在where子句中对字段进行函数操作,

      这将导致引擎放弃使用索引而进行全表扫描。如:

     select id from t where substring(name,1,3)='abc'   --name

     select id from t wheredatediff(day,createdate,'2005-11-30')=0--‘2005-11-30’ 

     生成的id应改为:

     select id from t where name like 'abc%'

     select id from t where createdate>='2005-11-30' andcreatedate<'2005-12-1'

10).不要在 where 子句中的“=”左边进行函数、算术运算或其他表达式运算,

     否则系统将可能无法正确使用索引。

11). 索引字段不是复合索引的前缀索引

      例如在使用索引字段作为条件时,如果该索引是复合索引,那么必须使用到该索引中的第一个字段作为条件时才能保证系统使用该索引,否则该索引将不会被使用,并且应尽可能的让字段顺序与索引顺序相一致。

 

2 .其他一些注意优化:

12). 不要写一些没有意义的查询,

       如需要生成一个空表结构:

       select col1,col2 into #t from t where 1=0

       这类代码不会返回任何结果集,但是会消耗系统资源的,应改成这样:create table #t(...)

13). 很多时候用 exists代替 in 是一个好的选择:

      select num from a where num in(select num from b)

      用下面的语句替换:

      select num from a where exists(select 1 from b wherenum=a.num)

14). 并不是所有索引对查询都有效,

      SQL是根据表中数据来进行查询优化的,当索引列有大量数据重复时,SQL查询可能不会去利用索引,如一表中有字段sexmalefemale几乎各一半,那么即使在sex上建了索引也对查询效率起不了作用。

15). 索引并不是越多越好,

      索引固然可以提高相应的select 的效率,但同时也降低了insert update 的效率,因为insert update 时有可能会重建索引,所以怎样建索引需要慎重考虑,视具体情况而定。一个表的索引数最好不要超过6个,若太多则应考虑一些不常使用到的列上建的索引是否有必要。

16).应尽可能的避免更新clustered 索引数据列,

      因为clustered 索引数据列的顺序就是表记录的物理存储顺序,一旦该列值改变将导致整个表记录的顺序的调整,会耗费相当大的资源。若应用系统需要频繁更新clustered 索引数据列,那么需要考虑是否应将该索引建为clustered 索引。

17).尽量使用数字型字段,

     若只含数值信息的字段尽量不要设计为字符型,这会降低查询和连接的性能,并会增加存储开销。这是因为引擎在处理查询和连接时会逐个比较字符串中每一个字符,而对于数字型而言只需要比较一次就够了。

18).尽可能的使用varchar/nvarchar 代替char/nchar

     因为首先变长字段存储空间小,可以节省存储空间,其次对于查询来说,在一个相对较小的字段内搜索效率显然要高些。

19).最好不要使用"*"返回所有: select* from t

    用具体的字段列表代替“*”,不要返回用不到的任何字段。

 

7. COUNT优化:

31) count(*)优于count(1)count(primary_key)

  很多人为了统计记录条数,就使用 count(1) 和 count(primary_key) 而不是 count(*) ,他们认为这样性能更好,其实这是一个误区。对于有些场景,这样做可能性能会更差,应为数据库对 count(*) 计数操作做了一些特别的优化。

32)count(column) 和 count(*) 是不一样的

  这个误区甚至在很多的资深工程师或者是 DBA 中都普遍存在,很多人都会认为这是理所当然的。实际上,count(column) 和 count(*) 是一个完全不一样的操作,所代表的意义也完全不一样。

  count(column) 是表示结果集中有多少个column字段不为空的记录

  count(*) 是表示整个结果集有多少条记录

 

1)innodb引擎在统计方面和myisam是不同的,Myisam内置了一个计数器,

 Count(*)在没有查询条件的情况下使用 selectcount(*) from table 的时候,Myisam直接可以从计数器中取出数据。而innodb必须全表扫描一次方能得到总的数量

InnoDB引擎:

[1]     数据文件和索引文件存储在一个文件中,主键索引默认直接指向数据存储位置。

[2]     二级索引存储指定字段的索引,实际的指向位置是主键索引。当我们通过二级索引统计数据的时候,无需扫描数据文件;而通过主键索引统计数据时,由于主键索引与数据文件存放在一起,所以每次都会扫描数据文件,所以主键索引统计没有二级索引效率高。

[3]     由于主键索引直接指向实际数据,所以当我们通过主键id查询数据时要比通过二级索引查询数据要快。

MyIAsm引擎

[1]     该引擎把每个表都分为几部分存储,比如用户表,包含user.frmuser.MYDuser.MYI

[2]     User.frm负责存储表结构

[3]     User.MYD负责存储实际的数据记录,所有的用户记录都存储在这个文件中

[4]     User.MYI负责存储用户表的所有索引,这里也包括主键索引。


转载自:http://blog.csdn.net/hguisu/article/details/5731629



相关推荐
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页