zoukankan      html  css  js  c++  java
  • 数据库

     
    1. 什么是存储过程?它有什么优点?
    答:存储过程是一组予编译的SQL语句,它的优点有:
        允许模块化程序设计,就是说只需要创建一次过程,以后在程序中就可以调用该过程任意次。
        允许更快执行,如果某操作需要执行大量SQL语句或重复执行,存储过程比SQL语句执行的要快。
        减少网络流量,例如一个需要数百行的SQL代码的操作有一条执行语句完成,不需要在网络中发送数百行代码。
        更好的安全机制,对于没有权限执行存储过程的用户,也可授权他们执行存储过程。
    2. oracle的存储过程和函数有什么区别?
    Oracle中的函数与存储过程的区别: 
        A:函数必须有返回值,而过程没有. 
        B:函数可以单独执行.而过程必须通过execute执行. 
        C:函数可以嵌入到SQL语句中执行.而过程不行. 
        其实我们可以将比较复杂的查询写成函数.然后到存储过程中去调用这些函数. 
    Oracle中的函数与存储过程的特点: 
        A. 一般来说,存储过程实现的功能要复杂一点,而函数的实现的功能针对性比较强。 
        B. 对于存储过程来说可以返回参数,而函数只能返回值或者表对象。     
        C.存储过程一般是作为一个独立的部分来执行,而函数可以作为查询语句的一个部分来调用,由于函数可以返回一个表对象,因此它可以在查询语句中位于FROM关键字的后面。
    3. 什么是事务?
    答:事务是指一个工作单元,它包含了一组数据操作命令,并且所有的命令作为一个整体一起向系统提交或撤消请求操作,即这组命令要么都执行,要么都不执行。
        原子性:事务必须是原子工作单元;对于其数据修改,要么全都执行,要么全都不执行。
        一致性:事务在完成时,必须使所有的数据都保持一致状态。在相关数据库中,所有规则都必须应用于事务的修改,以保持所有数据的完整性。事务结束时,所有的内部数据结构(如 B 树索引或双向链表)都必须是正确的。
        隔离性:由并发事务所作的修改必须与任何其它并发事务所作的修改隔离。事务查看数据时数据所处的状态,要么是另一并发事务修改它之前的状态,要么是另一事务修改它之后的状态,事务不会查看中间状态的数据。这称为可串行性,因为它能够重新装载起始数据,并且重播一系列事务,以使数据结束时的状态与原始事务执行的状态相同。
        持久性:事务完成之后,它对于系统的影响是永久性的。该修改即使出现系统故障也将一直保持。
    4. 什么是索引?它有什么优点?
    答:索引象书的目录类似,索引使数据库程序无需扫描整个表,就可以在其中找到所需要的数据,索引包含了一个表中包含值的列表,其中包含了各个值的行所存储的位置,索引可以是单个或一组列,索引提供的表中数据的逻辑位置,合理划分索引能够大大提高数据库性能。
    5. 什么是触发器,它有哪些优点?说说你遇到过的常见应用?
    答:触发器是一种特殊类型的存储过程,触发器主要通过事件触发而被执行的,触发器的优点:
    ①.强化约束,触发器能够提供比CHECK约束。
    ②.跟踪变化,触发器可以跟踪数据库内的操作,从而不允许未经允许许可的更新和变化。
    ③.联级运算,比如某个表上的触发器中包含对另一个表的数据操作,而该操作又导致该表上的触发器被触发。
    6. 触发器分为事前触发和事后触发的区别。语句级触发和行级触发有何区别?
    事前触发器运行于触发事件发生之前,通常可以获取事件之前和新的字段值
    事后触发器运行于触发事件发生之后。
    语句级触发器可以在语句执行前或后执行,
    行级触发在触发器所影响的每一行触发一次
    7. 视图是什么?游标是什么?
    答:视图是一种虚拟表,虚拟表具有和物理表相同的功能,可以对虚拟表进行增该查操作,视图通常是一个或多个表的行或列的子集,视图的结果更容易理解(修改视图对基表不影响),获取数据更容易(相比多表查询更方便),限制数据检索(比如需要隐藏某些行或列),维护更方便。
    游标对查询出来的结果集作为一个单元来有效的处理,游标可以定位在结果集的特定行、从结果集的当前位置检索一行或多行、可以对结果集中当前位置进行修改。
    8. 怎么优化数据库(在数据千万条记录的数据库中 )?

    (1)优化sql(查询顺序)和索引;

    (2)加缓存,memcached,redis;

    (3)都做了后,还是慢,就做主从复制或主主复制,读写分离,可以在应用层做,效率高,也可以用三方工具,第三方工具推荐360的atlas,其它的要么效率不高,要么没人维护;

    (4)mysql自带分区表,先试试这个,对你的应用是透明的,无需更改代码,但是sql语句是需要针对分区表做优化的,sql条件中要带上分区条件的列,从而使查询定位到少量的分区上,否则就会扫描全部分区,另外分区表还有一些坑,在这里就不多说了;

    (5)先做垂直拆分,其实就是根据你模块的耦合度,将一个大的系统分为多个小的系统,也就是分布式系统;

    (6)水平切分,针对数据量大的表,这一步最麻烦,最能考验技术水平,要选择一个合理的sharding key,为了有好的查询效率,表结构也要改动,做一定的冗余,应用也要改,sql中尽量带sharding key,将数据定位到限定的表上去查,而不是扫描全部的表;

    mysql数据库一般都是按照这个步骤去演化的,成本也是由低到高

    9. 如何优化SQL语句
        ①. 对操作符的优化 尽量不采用不利用索引的操作符
        如:in ,not in , is nul, is not null,<>等
        ②. 对条件字段的一些优化
         采用函数处理的字段不能利用索引,
         进行了显式或隐式的运算的字段不能进行索引
         条件内包括了多个本表的字段运算时不能进行索引
        ③. 在业务密集的SQL当中WHERE后面的条件顺序影响
        ④. 应用ORACLE的HINT(提示)处理
        ⑤. 查询表顺序的影响 
    10. 使用索引查询一定能提高查询的性能吗?为什么?
    不能。如果返回的行数目较大,使用全表扫描的性能较好。
    11. 操作符优化
    ①.IN 操作符
    用IN写出来的SQL的优点是比较容易写及清晰易懂,这比较适合现代软件开发的风格。但是用IN的SQL性能总是比较低的,从Oracle执行的步骤来分析用IN的SQL与不用IN的SQL有以下区别:
    ORACLE试图将其转换成多个表的连接,如果转换不成功则先执行IN里面的子查询,再查询外层的表记录,如果转换成功则直接采用多个表的连接方式查询。由此可见用IN的SQL至少多了一个转换的过程。一般的SQL都可以转换成功,但对于含有分组统计等方面的SQL就不能转换了。
    推荐方案:在业务密集的SQL当中尽量不采用IN操作符,用EXISTS 方案代替。
    ②.NOT IN操作符
    此操作是强列不推荐使用的,因为它不能应用表的索引。
    推荐方案:用NOT EXISTS 方案代替
    ③.IS NULL 或IS NOT NULL操作(判断字段是否为空)
    判断字段是否为空一般是不会应用索引的,因为索引是不索引空值的。
    推荐方案:用其它相同功能的操作运算代替,如:a is not null 改为 a>0 或a>’’等。不允许字段为空,而用一个缺省值代替空值,如申请中状态字段不允许为空,缺省为申请。
    ④.> 及 < 操作符(大于或小于操作符)
    大于或小于操作符一般情况下是不用调整的,因为它有索引就会采用索引查找,但有的情况下可以对它进行优化,如一个表有100万记录,一个数值型字段A,30万记录的A=0,30万记录的A=1,39万记录的A=2,1万记录的A=3。那么执行A>2与A>=3的效果就有很大的区别了,因为A>2时ORACLE会先找出为2的记录索引再进行比较,而A>=3时ORACLE则直接找到=3的记录索引。
    ⑤.LIKE操作符
    LIKE操作符可以应用通配符查询,里面的通配符组合可能达到几乎是任意的查询,但是如果用得不好则会产生性能上的问题,如LIKE ‘%5400%’ 这种查询不会引用索引,而LIKE ‘X5400%’则会引用范围索引。
    一个实际例子:用YW_YHJBQK表中营业编号后面的户标识号可来查询营业编号 YY_BH LIKE ‘%5400%’ 这个条件会产生全表扫描,如果改成YY_BH LIKE ’X5400%’ OR YY_BH LIKE ’B5400%’ 则会利用YY_BH的索引进行两个范围的查询,性能肯定大大提高。
    ⑥.UNION操作符
    UNION在进行表链接后会筛选掉重复的记录,所以在表链接后会对所产生的结果集进行排序运算,删除重复的记录再返回结果。实际大部分应用中是不会产生重复的记录,最常见的是过程表与历史表UNION。如:
    select * from gc_dfys
    union
    select * from ls_jg_dfys
    这个SQL在运行时先取出两个表的结果,再用排序空间进行排序删除重复的记录,最后返回结果集,如果表数据量大的话可能会导致用磁盘进行排序。
    推荐方案:采用UNION ALL操作符替代UNION,因为UNION ALL操作只是简单的将两个结果合并后就返回。
    select * from gc_dfys
    union all
    select * from ls_jg_dfys
    12. 说说你知道的一些关于查询优化的方案?
    1.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引。
    2.应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描,如:?
         select id from t where num is null?
         可以在num上设置默认值0,确保表中num列没有null值,然后这样查询:?
         select id from t where num=0
    3.应尽量避免在 where 子句中使用!=或<>操作符,否则将引擎放弃使用索引而进行全表扫描。
    4.应尽量避免在 where 子句中使用 or 来连接条件,否则将导致引擎放弃使用索引而进行全表扫描,如:?
         select id from t where num=10 or num=20?
         可以这样查询:?
         select id from t where num=10?
         union all?
         select id from t where num=20
    5.in 和 not in 也要慎用,否则会导致全表扫描,如:?
         select id from t where num in(1,2,3)?
         对于连续的数值,能用 between 就不要用 in 了:?
         select id from t where num between 1 and 3
    6.下面的查询也将导致全表扫描:?
         select id 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 where num/2=100?
         应改为:?
         select id from t where num=100*2
    9.应尽量避免在where子句中对字段进行函数操作,这将导致引擎放弃使用索引而进行全表扫描。如:?
         select id from t where substring(name,1,3)='abc'--name以abc开头的id?
         select id from t where datediff(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' and createdate<'2005-12-1'
    10.不要在 where 子句中的“=”左边进行函数、算术运算或其他表达式运算,否则系统将可能无法正确使用索引。
    11.在使用索引字段作为条件时,如果该索引是复合索引,那么必须使用到该索引中的第一个字段作为条件时才能保证系统使用该索引,否则该索引将不会被使用,并且应尽可能的让字段顺序与索引顺序相一致。
    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 where num=a.num)
    14.并不是所有索引对查询都有效,SQL是根据表中数据来进行查询优化的,当索引列有大量数据重复时,SQL查询可能不会去利用索引,如一表中有字段sex,male、female几乎各一半,那么即使在sex上建了索引也对查询效率起不了作用。
    15.索引并不是越多越好,索引固然可以提高相应的 select 的效率,但同时也降低了 insert 及 update 的效率,因为 insert 或 update 时有可能会重建索引,所以怎样建索引需要慎重考虑,视具体情况而定。一个表的索引数最好不要超过6个,若太多则应考虑一些不常使用到的列上建的索引是否有必要。
    16.应尽可能的避免更新 clustered 索引数据列,因为 clustered 索引数据列的顺序就是表记录的物理存储顺序,一旦该列值改变将导致整个表记录的顺序的调整,会耗费相当大的资源。若应用系统需要频繁更新 clustered 索引数据列,那么需要考虑是否应将该索引建为 clustered 索引。
    17.尽量使用数字型字段,若只含数值信息的字段尽量不要设计为字符型,这会降低查询和连接的性能,并会增加存储开销。这是因为引擎在处理查询和连接时会逐个比较字符串中每一个字符,而对于数字型而言只需要比较一次就够了。
    18.尽可能的使用 varchar/nvarchar 代替 char/nchar ,因为首先变长字段存储空间小,可以节省存储空间,其次对于查询来说,在一个相对较小的字段内搜索效率显然要高些。
    19.任何地方都不要使用 select * from t ,用具体的字段列表代替“*”,不要返回用不到的任何字段。
    20.尽量使用表变量来代替临时表。如果表变量包含大量数据,请注意索引非常有限(只有主键索引)。
    21.避免频繁创建和删除临时表,以减少系统表资源的消耗。
    22.临时表并不是不可使用,适当地使用它们可以使某些例程更有效,例如,当需要重复引用大型表或常用表中的某个数据集时。但是,对于一次性事件,最好使用导出表。
    23.在新建临时表时,如果一次性插入数据量很大,那么可以使用 select into 代替 create table,避免造成大量 log ,以提高速度;如果数据量不大,为了缓和系统表的资源,应先create table,然后insert。
    24.如果使用到了临时表,在存储过程的最后务必将所有的临时表显式删除,先 truncate table ,然后 drop table ,这样可以避免系统表的较长时间锁定。
    25.尽量避免使用游标,因为游标的效率较差,如果游标操作的数据超过1万行,那么就应该考虑改写。
    26.使用基于游标的方法或临时表方法之前,应先寻找基于集的解决方案来解决问题,基于集的方法通常更有效。
    27.与临时表一样,游标并不是不可使用。对小型数据集使用 FAST_FORWARD 游标通常要优于其他逐行处理方法,尤其是在必须引用几个表才能获得所需的数据时。在结果集中包括“合计”的例程通常要比使用游标执行的速度快。如果开发时间允许,基于游标的方法和基于集的方法都可以尝试一下,看哪一种方法的效果更好。
    28.在所有的存储过程和触发器的开始处设置 SET NOCOUNT ON ,在结束时设置 SET NOCOUNT OFF 。无需在执行存储过程和触发器的每个语句后向客户端发送 DONE_IN_PROC 消息。
    29.尽量避免大事务操作,提高系统并发能力。
    30.尽量避免向客户端返回大数据量,若数据量过大,应该考虑相应需求是否合理。
    31. 分别说说DDL、DML、DCL、DQL分别指的是什么?
    l  DDL(Data Definition Language):数据定义语言,用来定义数据库对象:库、表、列等;
                 创建数据库:CREATE DATABASE [IF NOT EXISTS] mydb1;
       删除数据库:DROP DATABASE [IF EXISTS] mydb1;
       修改数据库编码:ALTER DATABASE mydb1 CHARACTER SET utf8
    l  DML(Data Manipulation Language):数据操作语言,用来定义数据库记录(数据);
       插入数据:INSERT INTO 表名(列名1,列名2, …) VALUES(值1, 值2)
       修改数据:UPDATE 表名 SET 列名1=值1, … 列名n=值n [WHERE 条件]
       删除数据:DELETE FROM 表名 [WHERE 条件]
    l  DCL(Data Control Language):数据控制语言,用来定义访问权限和安全级别;
       创建用户:CREATE USER 用户名@地址 IDENTIFIED BY '密码';
       授权用户:GRANT 权限1, … , 权限n ON 数据库.* TO 用户名
       撤销授权:REVOKE权限1, … , 权限n ON 数据库.* FORM 用户名
       查看权限:SHOW GRANTS FOR 用户名
       删除用户:DROP USER 用户名
       修改密码:USE mysql;
                UPDATE USER SET PASSWORD=PASSWORD(‘密码’) WHERE User=’用户名’ and Host=’IP’;
                FLUSH PRIVILEGES;
     
    l  DQL(Data Query Language):数据查询语言,用来查询记录(数据)。
            SELECT selection_list /*要查询的列名称*/
       FROM table_list /*要查询的表名称*/
       WHERE condition /*行条件*/
       GROUP BY grouping_columns /*对结果分组*/
       HAVING condition /*分组后的行条件*/
       ORDER BY sorting_columns /*对结果分组*/
       LIMIT offset_start, row_count /*结果限定*/
    32. 数据库中,我们对主键有哪些要求?
        非空、唯一、可引用!
    33. 分别说说MySQL和oracle的分页?
    oracle使用rownum加上嵌套子查询完成分页功能
    SELECT * FROM
    (
    SELECT A.*, ROWNUM RN
    FROM (SELECT * FROM TABLE_NAME) A
    WHERE ROWNUM <= 40
    )
    WHERE RN >= 21
    MySQL使用的是limit函数
    SELECT * FROM table LIMIT 5,10; //查询的是第6条到第15条数据,注意,10位偏移量。
     
     
     
    一、交叉连接(CROSS JOIN)
     
    交叉连接(CROSS JOIN):有两种,显式的和隐式的,不带ON子句,返回的是两表的乘积,也叫笛卡尔积。
    例如:下面的语句1和语句2的结果是相同的。
    语句1:隐式的交叉连接,没有CROSS JOIN。
    SELECT O.ID, O.ORDER_NUMBER, C.ID, C.NAME
    FROM ORDERS O , CUSTOMERS C
    WHERE O.ID=1;
    语句2:显式的交叉连接,使用CROSS JOIN。
    SELECT O.ID,O.ORDER_NUMBER,C.ID,
    C.NAME
    FROM ORDERS O CROSS JOIN CUSTOMERS C
    WHERE O.ID=1; 语句1和语句2的结果是相同的,查询结果如下:
    二、内连接(INNER JOIN)
     
    内连接(INNER JOIN):有两种,显式的和隐式的,返回连接表中符合连接条件和查询条件的数据行。(所谓的链接表就是数据库在做查询形成的中间表)。
     
    例如:下面的语句3和语句4的结果是相同的。
    语句3:隐式的内连接,没有INNER JOIN,形成的中间表为两个表的笛卡尔积。
    SELECT O.ID,O.ORDER_NUMBER,C.ID,C.NAME
    FROM CUSTOMERS C,ORDERS O
    WHERE C.ID=O.CUSTOMER_ID;
     
    语句4:显示的内连接,一般称为内连接,有INNER JOIN,形成的中间表为两个表经过ON条件过滤后的笛卡尔积。
    SELECT O.ID,O.ORDER_NUMBER,C.ID,C.NAME
    FROM CUSTOMERS C INNER JOIN ORDERS O ON C.ID=O.CUSTOMER_ID;
    语句3和语句4的查询结果:
     
    三、外连接(OUTER JOIN):外连不但返回符合连接和查询条件的数据行,还返回不符合条件的一些行。外连接分三类:左外连接(LEFT OUTER JOIN)、右外连接(RIGHT OUTER JOIN)和全外连接(FULL OUTER JOIN)。
    三者的共同点是都返回符合连接条件和查询条件(即:内连接)的数据行。不同点如下:
    左外连接还返回左表中不符合连接条件单符合查询条件的数据行。
    右外连接还返回右表中不符合连接条件单符合查询条件的数据行。
    全外连接还返回左表中不符合连接条件单符合查询条件的数据行,并且还返回右表中不符合连接条件单符合查询条件的数据行。全外连接实际是上左外连接和右外连接的数学合集(去掉重复),即“全外=左外 UNION 右外”。
    说明:左表就是在“(LEFT OUTER JOIN)”关键字左边的表。右表当然就是右边的了。在三种类型的外连接中,OUTER 关键字是可省略的。
    下面举例说明:
     
    语句5:左外连接(LEFT OUTER JOIN)
    SELECT O.ID,O.ORDER_NUMBER,O.CUSTOMER_ID,C.ID,C.NAME
    FROM ORDERS O LEFT OUTER JOIN CUSTOMERS C ON C.ID=O.CUSTOMER_ID;
    语句6:右外连接(RIGHT OUTER JOIN)
    SELECT O.ID,O.ORDER_NUMBER,O.CUSTOMER_ID,C.ID,C.NAME
    FROM ORDERS O RIGHT OUTER JOIN CUSTOMERS C ON C.ID=O.CUSTOMER_ID;
    注意:WHERE条件放在ON后面查询的结果是不一样的。例如:
     
    语句7:WHERE条件独立。
    SELECT O.ID,O.ORDER_NUMBER,O.CUSTOMER_ID,C.ID,C.NAME
    FROM ORDERS O LEFT OUTER JOIN CUSTOMERS C ON C.ID=O.CUSTOMER_ID
    WHERE O.ORDER_NUMBER<>'MIKE_ORDER001';
     
    语句8:将语句7中的WHERE条件放到ON后面。
    SELECT O.ID,O.ORDER_NUMBER,O.CUSTOMER_ID,C.ID,C.NAME
    FROM ORDERS O LEFT OUTER JOIN CUSTOMERS C ON C.ID=O.CUSTOMER_ID AND O.ORDER_NUMBER<>'MIKE_ORDER001';
     
    从语句7和语句8查询的结果来看,显然是不相同的,语句8显示的结果是难以理解的。因此,推荐在写连接查询的时候,ON后面只跟连接条件,而对中间表限制的条件都写到WHERE子句中。
     
    语句9:全外连接(FULL OUTER JOIN)。
    SELECT O.ID,O.ORDER_NUMBER,O.CUSTOMER_ID,C.ID,C.NAME
    FROM ORDERS O FULL OUTER JOIN CUSTOMERS C ON C.ID=O.CUSTOMER_ID;
    注意:MySQL是不支持全外的连接的,这里给出的写法适合Oracle和DB2。但是可以通过左外和右外求合集来获取全外连接的查询结果。下图是上面SQL在Oracle下执行的结果:
    语句10:左外和右外的合集,实际上查询结果和语句9是相同的。
    SELECT O.ID,O.ORDER_NUMBER,O.CUSTOMER_ID,C.ID,C.NAME
    FROM ORDERS O LEFT OUTER JOIN CUSTOMERS C ON C.ID=O.CUSTOMER_ID
    UNION
    SELECT O.ID,O.ORDER_NUMBER,O.CUSTOMER_ID,C.ID,C.NAME
    FROM ORDERS O RIGHT OUTER JOIN CUSTOMERS C ON C.ID=O.CUSTOMER_ID;
    语句9和语句10的查询结果是相同的,如下:
     
    四、联合连接(UNION JOIN):这是一种很少见的连接方式。Oracle、MySQL均不支持,其作用是:找出全外连接和内连接之间差异的所有行。这在数据分析中排错中比较常用。也可以利用数据库的集合操作来实现此功能。
    语句11:联合查询(UNION JOIN)例句,还没有找到能执行的SQL环境。
    SELECT O.ID,O.ORDER_NUMBER,O.CUSTOMER_ID,C.ID,C.NAME
    FROM ORDERS O UNION JOIN CUSTOMERS C ON C.ID=O.CUSTOMER_ID
    语句12:语句11在DB2下的等价实现。还不知道DB2是否支持语句11呢!
    SELECT O.ID,O.ORDER_NUMBER,O.CUSTOMER_ID,C.ID,C.NAME
    FROM ORDERS O FULL OUTER JOIN CUSTOMERS C ON C.ID=O.CUSTOMER_ID
    EXCEPT
    SELECT O.ID,O.ORDER_NUMBER,O.CUSTOMER_ID,C.ID,C.NAME
    FROM ORDERS O INNER JOIN CUSTOMERS C ON C.ID=O.CUSTOMER_ID;
     
    语句13:语句11在Oracle下的等价实现。
    SELECT O.ID,O.ORDER_NUMBER,O.CUSTOMER_ID,C.ID,C.NAME
    FROM ORDERS O FULL OUTER JOIN CUSTOMERS C ON C.ID=O.CUSTOMER_ID
    MINUS
    SELECT O.ID,O.ORDER_NUMBER,O.CUSTOMER_ID,C.ID,C.NAME
    FROM ORDERS O INNER JOIN CUSTOMERS C ON C.ID=O.CUSTOMER_ID;
    查询结果如下:
     
     
    sql语句优化?
     
    1.查询的模糊匹配
    尽量避免在一个复杂查询里面使用 LIKE '%parm1%'—— 红色标识位置的百分号会导致相关列的索引无法使用,最好不要用。
    解决办法:
    其实只需要对该脚本略做改进,查询速度便会提高近百倍。改进方法如下:
    a、修改前台程序——把查询条件的供应商名称一栏由原来的文本输入改为下拉列表,用户模糊输入供应商名称时,直接在前台就帮忙定位到具体的供应商,这样在调用后台程序时,这列就可以直接用等于来关联了。
    b、直接修改后台——根据输入条件,先查出符合条件的供应商,并把相关记录保存在一个临时表里头,然后再用临时表去做复杂关联。
    2.索引问题
    在做性能跟踪分析过程中,经常发现有不少后台程序的性能问题是因为缺少合适索引造成的,有些表甚至一个索引都没有。这种情况往往都是因为在设计表时,没去定义索引,而开发初期,由于表记录很少,索引创建与否,可能对性能没啥影响,开发人员因此也未多加重视。然一旦程序发布到生产环境,随着时间的推移,表记录越来越多。这时缺少索引,对性能的影响便会越来越大了。
    法则:不要在建立的索引的数据列上进行下列操作:
    避免对索引字段进行计算操作
    避免在索引字段上使用not,<>,!=
    避免在索引列上使用IS NULL和IS NOT NULL
    避免在索引列上出现数据类型转换
    避免在索引字段上使用函数
    避免建立索引的列中使用空值
    3.复杂操作
    部分UPDATE、SELECT 语句 写得很复杂(经常嵌套多级子查询)——可以考虑适当拆成几步,先生成一些临时数据表,再进行关联操作。
    4.update
    同一个表的修改在一个过程里出现好几十次,如:
    update table1  
    set col1=...  
    where col2=...;  
    update table1  
    set col1=...  
    where col2=...  
    ... 
    这类脚本其实可以很简单就整合在一个UPDATE语句来完成(前些时候在协助xxx项目做性能问题分析时就发现存在这种情况)
    5.在可以使用UNION ALL的语句里,使用了UNION
    UNION 因为会将各查询子集的记录做比较,故比起UNION ALL ,通常速度都会慢上许多。一般来说,如果使用UNION ALL能满足要求的话,务必使用UNION ALL。还有一种情况大家可能会忽略掉,就是虽然要求几个子集的并集需要过滤掉重复记录,但由于脚本的特殊性,不可能存在重复记录,这时便应该使用 UNION ALL,如xx模块的某个查询程序就曾经存在这种情况,见,由于语句的特殊性,在这个脚本中几个子集的记录绝对不可能重复,故可以改用UNION ALL)。
    6.在WHERE 语句中,尽量避免对索引字段进行计算操作
    这个常识相信绝大部分开发人员都应该知道,但仍有不少人这么使用,我想其中一个最主要的原因可能是为了编写写简单而损害了性能,那就不可取了。9月份在对XX系统做性能分析时发现,有大量的后台程序存在类似用法,如:where trunc(create_date)=trunc(:date1),虽然已对create_date 字段建了索引,但由于加了TRUNC,使得索引无法用上。此处正确的写法应该是where create_date>=trunc(:date1) and create_date< pre=""><>或者是where create_date between trunc(:date1) and trunc(:date1)+1-1/(24*60*60)。
    注意:因between 的范围是个闭区间(greater than or equal to low value and less than or equal to high value.),故严格意义上应该再减去一个趋于0的小数,这里暂且设置成减去1秒(1/(24*60*60)),如果不要求这么精确的话,可以略掉这步。
    7.对Where 语句的法则
    7.1 避免在WHERE子句中使用in,not  in,or 或者having。
    可以使用 exist 和not exist代替in和not in。
    可以使用表链接代替 exist。Having可以用where代替,如果无法代替可以分两步处理。
    例子
    SELECT * FROM ORDERS WHERE CUSTOMER_NAME NOT IN   
    (SELECT CUSTOMER_NAME FROM CUSTOMER)  
    优化
    SELECT * FROM ORDERS WHERE CUSTOMER_NAME not exist   
    (SELECT CUSTOMER_NAME FROM CUSTOMER) 
    7.2 不要以字符格式声明数字,要以数字格式声明字符值。(日期同样)否则会使索引无效,产生全表扫描。
    例子使用:
    SELECT emp.ename, emp.job FROM emp WHERE emp.empno = 7369;
    --不要使用:
    SELECT emp.ename, emp.job FROM emp WHERE emp.empno = '7369'
    8.对Select语句的法则
    在应用程序、包和过程中限制使用select * from table这种方式。看下面例子
    --使用
    SELECT empno,ename,category FROM emp WHERE empno = '7369'
    --而不要使用
    SELECT * FROM emp WHERE empno = '7369'
    9. 排序
    避免使用耗费资源的操作,带有DISTINCT,UNION,MINUS,INTERSECT,ORDER BY的SQL语句会启动SQL引擎 执行,耗费资源的排序(SORT)功能. DISTINCT需要一次排序操作, 而其他的至少需要执行两次排序。
    10.临时表
    慎重使用临时表可以极大的提高系统性能。
    11.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引。
    12.应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描,如:
    select id from t where num is null
    可以在num上设置默认值0,确保表中num列没有null值,然后这样查询:
    select id from t where num=0
    13.应尽量避免在 where 子句中使用!=或<>操作符,否则将引擎放弃使用索引而进行全表扫描。
    14.应尽量避免在 where 子句中使用 or 来连接条件,否则将导致引擎放弃使用索引而进行全表扫描,如:
    select id from t where num=10 or num=20
    可以这样查询:
    select id from t where num=10
    union all
    select id from t where num=20
    15.in 和 not in 也要慎用,否则会导致全表扫描,如:
    select id from t where num in(1,2,3)
    对于连续的数值,能用 between 就不要用 in 了:
    select id from t where num between 1 and 3
    16.下面的查询也将导致全表扫描:
    select id from t where name like '%abc%'
    17.应尽量避免在 where 子句中对字段进行表达式操作,这将导致引擎放弃使用索引而进行全表扫描。如:
    select id from t where num/2=100
    应改为:
    select id from t where num=100*2
    18.应尽量避免在where子句中对字段进行函数操作,这将导致引擎放弃使用索引而进行全表扫描。如:
    select id from t where substring(name,1,3)='abc'--name以abc开头的id
    应改为:
    select id from t where name like 'abc%'
    19.不要在 where 子句中的“=”左边进行函数、算术运算或其他表达式运算,否则系统将可能无法正确使用索引。
    20.在使用索引字段作为条件时,如果该索引是复合索引,那么必须使用到该索引中的第一个字段作为条件时才能保证系统使用该索引,
    否则该索引将不会被使用,并且应尽可能的让字段顺序与索引顺序相一致。
     
    21.不要写一些没有意义的查询,如需要生成一个空表结构:
    select col1,col2 into #t from t where 1=0
    这类代码不会返回任何结果集,但是会消耗系统资源的,应改成这样:
    create table #t(...)
    22.很多时候用 exists 代替 in 是一个好的选择:
    select num from a where num in(select num from b)
    用下面的语句替换:
    select num from a where exists(select 1 from b where num=a.num)
    23.并不是所有索引对查询都有效,SQL是根据表中数据来进行查询优化的,当索引列有大量数据重复时,SQL查询可能不会去利用索引,
    如一表中有字段sex,male、female几乎各一半,那么即使在sex上建了索引也对查询效率起不了作用。
    24.索引并不是越多越好,索引固然可以提高相应的 select 的效率,但同时也降低了 insert 及 update 的效率,
    因为 insert 或 update 时有可能会重建索引,所以怎样建索引需要慎重考虑,视具体情况而定。
    一个表的索引数最好不要超过6个,若太多则应考虑一些不常使用到的列上建的索引是否有必要。
     
    25.尽量使用数字型字段,若只含数值信息的字段尽量不要设计为字符型,这会降低查询和连接的性能,并会增加存储开销。
    这是因为引擎在处理查询和连接时会逐个比较字符串中每一个字符,而对于数字型而言只需要比较一次就够了。
     
    26.尽可能的使用 varchar 代替 char ,因为首先变长字段存储空间小,可以节省存储空间,
    其次对于查询来说,在一个相对较小的字段内搜索效率显然要高些。
     
    27.任何地方都不要使用 select * from t ,用具体的字段列表代替“*”,不要返回用不到的任何字段。
     
    28.避免频繁创建和删除临时表,以减少系统表资源的消耗。
     
    29.在新建临时表时,如果一次性插入数据量很大,那么可以使用 select into 代替 create table,避免造成大量 log ,
    以提高速度;如果数据量不大,为了缓和系统表的资源,应先create table,然后insert。
     
    30.尽量避免使用游标,因为游标的效率较差,如果游标操作的数据超过1万行,那么就应该考虑改写。
    31.使用基于游标的方法或临时表方法之前,应先寻找基于集的解决方案来解决问题,基于集的方法通常更有效。
    32.尽量避免大事务操作,提高系统并发能力。
     
    33.尽量避免向客户端返回大数据量,若数据量过大,应该考虑相应需求是否合理。
     
     
     
    什么是存储过程?
    存储过程是由流控制和SQL语句书写的过程,这个过程经编译和优化后存储在数据库服务器中,应用程序使用时只要调用即可。在ORACLE中,若干个有联系的过程可以组合在一起构成程序包。
    存储过程优点
    1. 速度快。存储过程只在创造时进行编译,以后每次执行存储过程都不需再重新编译,而一般SQL 语句每执行一次就编译一次,所以使用存储过程可提高数据库执行速度。
    2. 写程序简单。采用存储过程调用类,调用任何存储过程都只要1-2行代码。
    3. 升级、维护方便。存储过程会使得维护起来更加方便,因为通常修改一个存储过程要比在一个已经发布的组件中修改SQL语句更加方便;
    4. 能够缓解网络带宽。因为可以批量执行SQL语句而不是从客户端发送超负载的请求。尤其对于较为复杂的逻辑,减少了网络流量之间的消耗。
    5. 可保证数据的安全性和完整性。通过存储过程可以使没有权限的用户在控制之下间接地存取数据库,从而保证数据的安全。通过存储过程可以使相关的动作在一起发生,从而可以维护数据库的完整性。
    6. 增强安全性。
    1. 通过向用户授予对存储过程(而不是基于表)的访问权限,它们可以提供对特定数据的访问。
    2. 提高代码安全,防止 SQL注入(但未彻底解决,例如,将数据操作语言--DML,附加到输入参数)。
    3. SqlParameter 类指定存储过程参数的数据类型,作为深层次防御性策略的一部分,可以验证用户提供的值类型(但也不是万无一失,还是应该传递至数据库前得到附加验证)。
     
    存储过程缺点
    1. 可移植性差。由于存储过程将应用程序绑定到 SQL Server,因此使用存储过程封装业务逻辑将限制应用程序的可移植性。如果应用程序的可移植性在您的环境中非常重要,则将业务逻辑封装在不特定于 RDBMS 的中间层中可能是一个更佳的选择。
    2. 代码可读性差,相当难维护。
    3. 不支持群集
    4. 大量采用存储过程进行业务逻辑的开发致命的缺点是很多存储过程不支持面向对象的设计,无法采用面向对象的方式将业务逻辑进行封装,从而无法形成通用的可支持复用的业务逻辑框架。
    5. 如果在一个程序系统中大量的使用存储过程,到程序交付使用的时候随着用户需求的增加会导致数据结构的变化,接着就是系统的相关问题了,最后如果用户想维护该系统可以说是很难很难、而且代价是空前的,维护起来更麻烦。
    使用原则
    1. 当一个业务同时对多个表进行处理的时候采用存储过程比较合适。
    2. 复杂的数据处理用存储过程比较合适,如有些报表处理。
    3. 多条件多表联合查询,并做分页处理,用存储过程也比较适合。
    4. 使用存储过程,等需求变动,需要维护的时候,麻烦就来了。不应该大规模使用。
    5. 适当的使用存储过程,能够提高我们SQL查询的性能,以便于提高我们的工作效率。
     
     
    oracle如果要实现主键自增.怎么实现?mysql呢?
    MySQL:
    要实现主键的自动递增非常简单.只需要在主键定义的后面加上auto_increment即可
    默认情况下,序列从1开始,但是我们可以进行设置,ALTER TABLE xxx AUTO_INCREMENT = 10001; 
    Oracle:
    1. 建立一个表,
    create table account (
       aid                   INTEGER                         not null,
       atype                   CHAR(20)                        not null,
       hostname                 CHAR(20)                        not null,
       address                   CHAR(200)                       not null,
       undertaker                  CHAR(20)                        not null,
       underdate                   DATE                            not null,
       constraint PK_account primary key (aid)
    );
     
    1. 建立一个sequence序列:
    CREATE SEQUENCE book_Sequence
     INCREMENT BY 1   -- 每次加几个  
         START WITH 1     -- 从1开始计数  
         NOMAXVALUE       -- 不设置最大值  
         NOCYCLE ;         -- 一直累加,不循环
     
    1. 建立一个触发器:
    CREATE TRIGGER book_increase BEFORE
    insert ON account FOR EACH ROW
    begin
    select BOOK_SEQUENCE.nextval into :New.aid from dual;
    end;
     
     
    数据库优化:电商项目中设计某个商品表的过程当中,有四个字段商品id,商品价格price,商品数量count,商品金额total,说说为什么这样设计。
    1. 数据细分:
    电商项目一般有三个主要业务:查询、下单和付款,其中下单只涉及商品id、商品价格、商品数量和商品金额,将这四个属性单独创建一张表,可以降低查询和下单业务之间的影响,必要的话,还可以将查询和下单拆分成两个独立的系统。
    1. 数据安全:
    商品金额是计算好保存到数据库的,在使用时不用去界面获取,防止有人恶意篡改界面导致的金额过低问题
      

     数据备份:

    导出: (用户名 密码 表名 导出的表名)

    mysqldump --default-character-set=utf8 -hrm-vy19r48p4g68fac1c.mysql.rds.aliyuncs.com -yinpeizheng -p"mima" database4paas help_index > help_index.sql

    导入: (其实就是打开导出的SQL语句)

    mysql> source order_info1.sql

     

     数据操作记录:

    你操作的记录都在

    mysqlbinlog -vv --base64-output=decode-rows mysql-bin.000001

    文件保存在这个目录下

    /var/lib/mysql

     
     
     
     
     
     
  • 相关阅读:
    iPhone网络编程初体验
    va_list实现不定参数C函数
    iphone网络编程总结(链接)
    一周好文(4)
    10个迷惑新手的Cocoa&Objectivec开发问题
    Flash通过Action Script调用C++接口
    easyui表单对numberbox控件进行赋值需要注意
    asp.net生成缩略图及给原始图加水印
    用超链接在页面之间传值的注意事项(来自:http://www.souzz.net)
    超酷的分类导航代码
  • 原文地址:https://www.cnblogs.com/pzyin/p/7649792.html
Copyright © 2011-2022 走看看