手记

MySQL和Oracle相关

MySQL和Oracle的区别:

MySQL和Oracle都是流行的关系数据库管理系统(RDBMS),在世界各地广泛使用。大多数数据库以类似的方式工作。
二者有何区别?两个数据库的特性是不同的,所以与Oracle相比,MySQL的使用方式不同;与MySQL相比,Oracle的使用情况有所不同。它们的特点也是不同的。

1.本质的区别:

Oracle数据库是一个对象关系数据库管理系统(ORDBMS)。它通常被成为OracleRDBMS或简称为Oracle,是一个收费的数据库。
MySQL是一个开源的关系数据库管理系统(RDBMS)。它是世界上使用最多的RDBMS,作为服务器运行,提供多个数据库的多用户访问。它是一个开源、免费的数据库。

2.数据库安全性:

MySQL使用三个参数来验证用户,即用户名、密码和位置;Oracle使用了许多安全功能,如用户名,密码,配置文件,本地身份验证,外部身份验证,高级安全增强功能等。

3.SQL语法的区别:

Oracle的SQL语法与MySQL有很大不同。Oracle为称为PL/SQL的编程语言提供了更大的灵活性。Oracle的SQL*Plus工具提供了比MySQL更多的命令,用于生成报表输出和变量定义。

4.存储上的区别:

与Oracle相比,MySQL没有表空间,角色管理,快照,同义词和包以及自动存储管理。

5.对象名称的区别:

虽然某些模式对象名称在Oracle和MySQL中都不区分大小写,例如列,存储过程,索引等。但在某些情况下,两个数据库之间的区别大小写是不同的。
Oracle对所有对象名称都不区分大小写;而某些MySQL对象名称(如数据库和表)区分大小写(取决于底层操作系统)。

6.运行程序和外部程序支持:

Oracle数据库支持从数据库内部编写,编译和执行的几种编程语言。此外,为了传输数据,Oracle数据库使用XML。
MySQL不支持在系统内执行其他语言,也不支持XML。

7.MySQL和Oracle的字符数据类型比较:

两个数据库中支持的字符类型存在一些差异。对于字符类型,MySQL具有CHAR和VARCHAR,最大长度允许为65535字节(CHAR最多可以为255字节,VARCHAR为65535字节)。
而Oracle支持四种字符类型,即CHAR,NCHAR,VARCHAR2和NVARCHAR2;所有四种字符类型都需要至少1个字节长;CHAR和NCAHR最大可以是2000个字节,VARCHAR2和NVARCHAR2的最大限制是
4000个字节。可能会在最新版本中进行扩展。

8.MySQL和Oracle的额外功能比较:

MySQL数据库不支持其服务器上的任何功能,如Audit Vault。另一方面,Oracle支持其数据库服务器上的几个扩展和程序,例如Active Data Guard,Audit Vault,Partitioning和Data Mining等。

9.临时表的区别:

Oracle和MySQL以不同方式处理临时表。
在MySQL中,临时表是仅对当前用户会话可见的数据库对象,并且一旦会话结束,这些表将自动删除。
Oracle中临时表的定义与MySQL略有不同,因为临时表一旦创建就会存在,直到它们被显式删除,并且对具有适当权限的所有会话都可见。但是,临时表中的数据仅对数据插入表中的用户会话可见,
并且数据可能在事务或用户会话期间持续存在。

10.MySQL和Oracle中的备份类型:

Oracle提供不同类型的备份工具,如冷备份,热备份,导出,导入,数据泵。Oracle提供了最流行的称为RecoveryManager(RMAN)的备份实用程序。使用RMAN,我们可以使用极少的命令或存
储脚本自动化我们的备份调度和恢复数据库。
MySQL有mysqldump和mysqlhotcopy备份工具。在MySQL中没有像RMAN这样的实用程序。

11.Oracle和MySQL的数据库管理:

在数据库管理部分,Oracle DBA比MySQL DBA更有收益。与MySQL相比,Oracle DBA有很多可用的范围。

MySQL优化

一、比较运算符能用"!=“就不用”<>":
"!="增加了索引的使用几率。

二、明知只有一条查询结果,那就使用"LIMIT 1":
"LIMIT 1"可以避免全表扫面,找到对应结果就不会再继续扫描了。

三、为列选择合适的数据类型,而且要避免隐式类型转换

  • 能用TINYINT就不用SMALLINT,能用SMALLINE就不用INT,道理你懂得,磁盘和内存消耗越小越好嘛。
  • where子句中出现column字段的类型和传入的参数类型不一致的时候发生的类型转换,建议先确定where中的参数类型。

四、将大的delete,update or insert查询变成多个小查询
能写一个几十行、几百行的SQL语句是不是显得逼格很高?然而,为了达到更好的性能以及更好的数据控制,应将它们写成多个小查询。

五、尽量用union all代替union
union 和 union all 的差异主要是前者需要将结果集合并后再进行唯一性过滤操作,这就会涉及到排序,增加大量的CPU运算,加大资源消耗及延迟。而UNINON ALL不去重,效率高于UNION。当然,union all 的前提条件是两个结果集没有重复数据。或者如果结果集允许重复的话,尽量使用union all 代替 union 。

六、为获得相同结果集的多次执行,请保持SQL语句前后一致。这样做的目的是为了充分利用查询缓冲。
比如根据地域和产品ID查询产品价格,第一次使用了:
select price from order where id=‘123’ and region='BEIJING’
那么第二次同样的查询,请保持以上语句的一致性,比如不要将where语句里面的id和region位置调换顺序。

七、select语句务必指明字段名称,尽量避免使用"select * "
如果不查询表中的所有的列,尽量避免使用select *,因为它会进行全表扫描,不能有效利用索引,增加很多不必要的消耗(CPU、IO、内存、网络带宽),增大了数据库服务器的负担,以及它与应用程序客户端之间的网络IO开销。当表结构发生改变时,前段也需要更新。所以要求直接在select后面接上字段名。

八、where子句里面的列尽量被索引
只是”尽量“,并不是所有的列。因地制宜,根据实际情况进行调整,因为有时索引太多也会降低性能。

九、JOIN子句里面的列尽量被索引。同样只是”尽量“,并不是说所有的列。
LEFT JOIN A表为驱动表,INNER JOIN MySQL会自动找出那个数据少的表作用驱动表,RIGHT JOIN B表为驱动表。
注意:

  1. MySQL中没有full join,可以用以下方式来解决:
 select * from A left join B on B.name = A.name where B.name is null
 union all select * from B;
  1. 尽量使用inner join,避免left join:
    参与联合查询的表至少为2张表,一般都存在大小之分。如果连接方式是inner
    join,在没有其他过滤条件的情况下MySQL会自动选择小表作为驱动表,但是left
    join在驱动表的选择上遵循的是左边驱动右边的原则,即left join左边的表名为驱动表。
  2. 合理利用索引:
    被驱动表的索引字段作为on的限制字段。
  3. 利用小表去驱动大表
    从原理图能够直观的看出如果能够减少驱动表的话,减少嵌套循环中的循环次数,以减少 IO总量及CPU运算的次数。
  4. 巧用STRAIGHT_JOIN:
    inner join是由MySQL选择驱动表,但是有些特殊情况需要选择另个表作为驱动表,比如有group by、order by等「Using filesort」、「Using temporary」时。STRAIGHT_JOIN来强制连接顺序,在STRAIGHT_JOIN左边的表名就是驱动表,右边则是被驱动表。在使用STRAIGHT_JOIN有个前提条件是该查询是内连接,也就是inner join。其他链接不推荐使用STRAIGHT_JOIN,否则可能造成查询结果不准确。
    这个方式有时能减少3倍的时间。

十、order by 优化

  • ORDER BY 的列尽量被索引。OEDER BY的列如果被索引,性能也会更好
  • 不使用ORDER BY RAND()
select id from table order by rand() limit 1000;

上面的SQL语句,可优化为:

select id from table  t1 join (select rand() * (select max(id) from table ) as nid) t2 on t1.id > t2.nidlimit 1000;

十一、注意范围查询语句
对于联合索引来说,如果存在范围查询,比如between、>、<等条件时,会造成后面的索引字段失效。

十二、使用EXPLAIN关键字去查看执行计划。EXPLAIN可以检查索引使用情况以及扫描的行。

十三、SQL语句中IN包含的值不应过多
MySQL对于IN做了相应的优化,即将IN中的常量全部存储在一个数组里面,而且这个数组是排好序的。但是如果数值较多,产生的消耗也是比较大的。再例如:select id from t where num in(1,2,3) 对于连续的数值,能用between就不要用in了;再或者使用连接来替换。

十四、如果排序字段没有用到索引,就尽量少排序

十五、如果限制条件中其他字段没有索引,尽量少用 or
or两边的字段中,如果有一个不是索引字段,而其他条件也不是索引字段,会造成该查询不走索引的情况。很多时候使用 union all 或者是 union(必要的时候)的方式来代替“or” 会得到更好的效果。

十六、区分 in 和 exists、not in 和not exists

select * from tableA where id in (select id from tableB)

上面SQL语句相当于:

select * from tableA where exists(select * from tableB where tableB.id=tableA.id)

区分 in 和 exists 主要是造成了驱动顺序的改变(这是性能变化的关键)。如果是exists,那么以外层表为驱动表,先被访问,如果是IN,那么先执行子查询。所以IN适合于外表大而内表小的情况;exists适合于外表小而内表大的情况。

关于 not in 和 not exists,推荐使用not exists,不仅仅是效率问题,not in 可能存在逻辑问题。如何高效的写出一个替代 not exists 的SQL语句?

原SQL语句:

select colname … from tableA where a.id not in (select b.id from tableB)

高效的SQL语句:

select colname … from tableA left join tableB on where a.id = b.id where b.id is null

取出的结果集为A表不在B表中的数据。

十七、limit 优化。使用合理的分页方式以提高分页的效率

  1. 使用limit实现分页逻辑。不仅提高了性能,同时减少了不必要的数据库和应用间的网络传输。
  2. 当只需要一条数据的时候,使用limit 1,这是为了使EXPLAIN中type列达到const类型。
  3. 使用下面SQL语句做分页的时候,可能有人会发现,随着表数据量的增加,直接使用limit分页查询会越来越慢。
select id,name from product limit 89757, 20

优化的方法如下:可以取前一页的最大行数的id,然后根据这个最大的id来限制下一页的起点。比如此列中,上一页最大的 id 是89756。SQL可以采用如下的写法:

select id,name from product where id> 89756 limit 20

十八、避免在where子句中对字段进行null值判断
对于null的判断会导致引擎放弃使用索引而进行全表扫描

十九、避免在where子句中对字段进行表达式操作

比如:

select id,name from table where age*2=22;

中对字段就行了算术运算,这会造成引擎放弃使用索引,建议改成:

select id,name from table where age=22/2;

二十、对于联合索引来说,要遵守最左前缀法则

举列来说索引含有字段id、name、school,可以直接用id字段,也可以id、name这样的顺序,但是name;school都无法使用这个索引。所以在创建联合索引的时候一定要注意索引字段顺序,常用的查询字段放在最前面。

二十一、必要时可以使用force index来强制查询走某个索引
有的时候MySQL优化器采取它认为合适的索引来检索SQL语句,但是可能它所采用的索引并不是我们想要的。这时就可以采用forceindex来强制优化器使用我们制定的索引。

总结:SQL调优方法很多,同样的查询结果可以有很多种不同的查询方式。其实最好的方法就是在开发环境中用最贴近真实的数据集和硬件环境进行测试,然后再发布到生产环境中。

Oracle优化

基本SQL语句:
查询:select * from tab_name where conditions order by field1 desc;(精准查询) desc降序,asc升序
select * from tab_name where field1 like ‘%value1%’(模糊查询)
插入:insert into tab_name(field1,field2)values(value1,value2);
删除:delete from tab_name where conditions;
更新:update tab_name set field1=value1,field2=value2 where conditions;
提交数据:commit;
回滚数据:rollback;
总数:select count() from tab_name
求和:select sum(field1) as sumvalue from tab_name
平均:select avg(field1) as avgvalue from tab_name
最大:select max(field1) as maxvalue from tab_name
最小:select min(field1) as minvalue from tab_name
分组:grounp by:一张表,一旦分组完成后,查询只能得到组相关的信息。
between的用法,between限制查询数据范围时包括了边界值,not between不包括:
select * from tab_name where time between time1 and time2
select a,b,c from tab_name where a not between num1 and num2
in的用法:select * from tab_name where a[not] in (‘值1’,‘值2’,‘值3’,‘值4’)
两张关联表,删除主表中已经在副表中没有的信息:delete from tab1 where not exists (select * from tab2 where tab1.field1=tab2.field2)
四表联查:select * from a left inner join b on a.a=b.b right inner join c on a.a=c.c inner join d on a.a=d.d where conditions
查询相同条目并记录重复次数(大于2):SELECT a,count(a) FROM tab_name GROUP BY a HAVING count(
) > 2
创建数据库:create database database-name;
删除数据库:drop database database-name;
创建新表:create table depart(
dept_id int(11) not null auto_increment,
depr_name varchar(255) default null,
primary key(dept_id)
);
根据已有的表创建新表:
create table tab_new like tab_old;(使用旧表B创建新表A) (MySQL)
备注:此种方式在将表B复制到A时候会将表B完整的字段结构和索引复制到表A中来。但不会复制数据。
create table tab_new as select col1,col2… from tab_old definition only;
备注:此种方式只会将B表的字段结构复制到表A中来,但不会复制表B中的索引到表A中来。这种方式比较灵活可以在复制原来表结构的同时指定要复制哪些字段,并且自身复制表也可以
根据需要增加字段结构。
删除表:drop table tab_name;
新增表的别名:comment on tab_name col is '测试’
更改表名:alter table tab_oldName rename to tab_newName
增加一个列:alter table tab_name add column_name type
添加主键:alter table tab_name add primary key(col)
删除主键:alter table tab_name drop primary key(col) 一个数据表只可以有一个主键,所以不存在删除某一列的主键。
创建索引:create [unique] index idxname on tab_name(col…)
删除索引:drop index idxname; 索引是不可以更改的,想更改必须删除重新建。
创建视图:create view viewname as select statement;
删除视图:drop view viewname;

pro
查询锁:select * from dba_blockers;
查询被阻塞的会话:select * from dba_waiters;
显示两个表内的相同数据:select column_name from tab_old intersect select column_name from tab_new;

Oracle中的in参数的个数限制:
Oracle中in后括号中的参数个数有限制,Oracle 9i 中个数不能超过256,Oracle 10g个数不能超过1000。
当in的个数大于1000时,有以下两个解决办法:
(1)对参数进行处理,分成多个in,其中每个in列表中参数都小于1000。如 params in(1,2,3…1000) or params in(1001,1002…2000)。
不过这种方法性能和维护性方面不好
(2)将in后面的字符串改成子查询,将in里面的数据保存到临时表中,params in(select …from dual)

SQL语句中过滤条件where和having的区别:
where是一个约束声明,使用where约束来自数据库的数据,where是在结果返回之前起作用,where中不能使用聚合函数。
Having是一个过滤声明,是在查询返回结果集以后对查询结果进行的过滤操作,在Having中可以使用聚合函数。
在查询过程中聚合语句(sum,min,max,avg,count)要比having子句优先执行。而where子句在查询过程中执行优先级高于聚合语句。

1人推荐
随时随地看视频
慕课网APP