发布新日志

  • MySQL索引优化总结

    2017-10-31 08:28:28

         索引是一种特殊的文件(InnoDB数据表上的索引是表空间的一个组成部分),它们包含着对数据表里所有记录的引用指针。常见比喻是数据库索引好比是一本书前面的目录,能加快数据库的查询速度。那么为什么查索引比查记录要快呢?一是索引的算法不必整个索引扫描后才能定位到记录而扫描记录则必须全部扫描完,另外一个索引字段少文件小加载进内存更快甚至常驻内存。《高性能MySQl》书中提到MySQL索引对某个查询是否合适的三星索引评估准则,索引将相关行放在一起(避免扫描更多的索引)则可获取一星,返回结果都在索引中(避免再查表) 则获取两星,索引顺序与查询要求的返回顺序相同(避免再排序)则获得三星,优化时可参考朝这3个方面去优化。

         是否需要创建索引?1、索引并不是越多越好,特别是OLTP型的,因为更新(插入、删除、更新)数据时均可能要更新索引,那么整体更新时间就增加了,一般情况下索引越多更新数据越慢。2、数据量不多(一般不上万,还要跟表的关,如相当多字段又另当别论了)时也可不必创建索引,因为直接扫描数据可以比扫描索引再找数据更快。3、如果字段的索引基数很小,创建索引也没太多意义,甚至更慢。4、频繁更新的字段建议不使用索引,因为更新时也要更新索引,甚至导致B-Tree或B+Tree的分裂重组则更慢了。5、字段不在where中出现是不需要添加索引, where后含IS NULL   like ‘%输入符%’等条件,也不建议使用索引,因为 like "%_" 百分号在前不走索引, B-tree索引 is null不走索引(is not null会走,位图索引 is null,is not null 则都会走索引)6、 where 子句里对索引列使用不等于(<>),要看字段的数据情况,因为很多时候覆盖索引比直接扫描更慢,可能不走索引。

         如何创建索引?创建索引的方式一般有如下3种:1、创建索引,例如CREATE INDEX <索引的名字> ON tablename (列的列表);2、修改表,例如ALTER TABLE tablename ADD INDEX [索引的名字] (列的列表);3、创建表的时候指定索引,例如CREATE TABLE tablename ( [...], INDEX [索引的名字] (列的列表) )。创建索引时首先需要分析确认是否需要创建索引(参考上文),除了where,关联查询时join的字段一般也需要添加索引。然后考虑是创建单索引还是组合索引,注意索引的最左前缀原则即查询条件必须包括索引的最左部分。最后创建索引后通过查看执行计划验证是否有走索引,或通过强制走索引的方式验证是否有提高效率。
         索引是否有应用?创建完索引后还需要考虑此索引面向哪些查询,是否都有效(是否应用及效率是否有提高)。 MySQL查询优化器是基于代价(cost-based)的查询方式,根据查询语句依据多种索引,计算查询需要的代价,从而选择最优的索引方式生成查询计划。所以可能出现有索引却并未应用上的情况,不应用的场景总结主要如下:
    1. 如果条件中有or,即使其中有部分条件带索引也不会使用。要想使用or,又想让索引生效,只能将or条件中的每个列都加上索引(出现索引合并的话可能性能理差)。
    2. 组合索引,要符合最左前缀才会应用。
    3. like查询是以%开头不会应用索引。
    4. where 子句里对索引列上有数学运算,用不上索引。
    5. where 子句里对有索引列使用函数,用不上索引。
    6. 如果mysql估计使用全表扫描要比使用索引快,则不使用索引。如查询的数量是大表的大部分,应该是30%以上;或是小表。
    7. 统计数据不真实,需要用analyze收集统计信息
    8. 隐式转换导致索引失效,也是开发中经常会犯的错误。由于表的字段tu_mdn定义为varchar2(20),但在查询时把该字段作为number类型以where条件传给数据库,这样会导致索引失效.
    9. not in ,not exist可能不会用索引,参数6。
    10. B-tree索引 is null不走索引(is not null会走,位图索引 is null,is not null 则都会走索引)





  • Sql子查询

    2009-06-28 21:56:53

       Sql子查询即是当一个查询语句嵌套在另一个查询语句的查询条件中时叫做子查询也叫做嵌套子查询。根据子查询的返回结果不同,子查询又可分为单行子查询,多行子查询与多列子查询。现在如下三类子查询作说明,并假设有如下四个表记录学生选修课的成绩: Student(stId, stName); course(coId,coName); teacher(teId, teName); score(stId, teId, coId, score) 其中学生可以有多门选修课,一个老师也可以教多门课程。
       1> 单行子查询
       单行子查询是指子查询的返回结果只有一行数据。当主查询语句的条件语句中引用子查询结果时可用单行比较符号(=, >, <, >=, <=, <>)来进行比较。
       例子:查询名叫Kaka的学生的所有成绩 sql> Select score from score where stId=(select stId from Student where stName='Kaka');
       2> 多行子查询
       多行子查询即是子查询的返回结果是多行数据。当主查询语句的条件语句中引用子查询结果时必须用多行比较符号(IN,ALL,ANY)来进行比较。其中,IN的含义是匹配子查询结果中的任一个值即可,ALL则必须要符合子查询的所有值才可,ANY要符合子查询结果的任何一个值即可。而且须注意ALL 和ANY 操作符不能单独使用,而只能与单行比较符(=、>、< 、>= 、<= 、<>)结合使用。
       多行子查询使用IN操作符号例子:查询选修了老师名叫Rona(假设唯一)的学生名字 sql> select stName from Student where stId in(selectdistinct stId from score where teId=(select teId from teacher where teName='Rona'));
       多行子查询使用ALL操作符号例子:查询有一门以上的成绩高于Kaka的最高成绩的学生的名字 sql> select stName from Student where stId in(select distinct stId from score where score >all(select score from score where stId=(select stId from Student where stName= 'Kaka') ));
       多行子查询使用ANY操作符号例子:查询有一门以上的成绩高于Kaka的任何一门成绩的学生的名字 sql> select stName from Student where stId in(select distinct stId from score where score >any(select score from score where stId=(select stId from Student where stName='Kaka')));
       3> 多列子查询
       以上的单行与多行子查询的返回结果都是单列数据,而这个多例子查询顾名义当然就是返回结果是多列的数据。而多列子查询当然也可以返回单行或是多行的多列数据,当是单行多列的子查询时,主查询语句的条件语句中引用子查询结果时可用单行比较符号(=, >, <, >=, <=, <>)来进行比较;当是多行多列子查询时,主查询语句的条件语句中引用子查询结果时必须用多行比较符号(IN,ALL,ANY)来进行比较。
       具体跟以上两个并无太多不同,只是比较的不是单列而是多列数据而已。
       除了以上子查询,还有相关子查询。然后听说子查询嵌套多了性能影响较大,用关联可以改善性能,这两个问题就要再研究下先再总结出来了。
  • sql 语句_基本操作

    2008-05-10 00:22:14

    操作数据库:

    1.创造数据库:Create database database_name;

    2.删除数据库:Drop database database_name;

    3.创建新表:create table tabel_name(col1 type1 [not null] [primary key], col2 ...);

      以旧表创建新表:create table table_name_new like tab_old

                   create table table_new as select col1,col2,..from tab_old definition  only;

    4.删除表:drop table table_name;

    5.增加列:alter table table_name add column colname typename

      删除列 alter table table_name drop column coluname

    6.添加主键:alter table table_name add primary key (colName)

      删除主键:alter table table_name drop primary key(colName)

    7.创建索引:create [unique]index indexName on tableName(col...)

      删除索引:drop index indexName on tableName

    8.创建视图:create view viewname as select_statement

      删除视图:drop view viewName

    9.常用语句:选择:select * from table1 where 范围
    插入:insert into table1(field1,field2) values(value1,value2)
    删除:delete from table1 where 范围
    更新:update table1 set field1=value1 where 范围
    查找:select * from table1 where field1 like ’%value1%’   排序:select * from table1 order by field1,field2 [desc]
    总数:select count(field) as totalcount from table1
    求和:select sum(field1) as sumvalue from table1
    平均:select avg(field1) as avgvalue from table1
    最大:select max(field1) as maxvalue from table1
    最小:select min(field1) as minvalue from table1

Open Toolbar