精华内容
下载资源
问答
  • 在SQLServer数据库中,我们在查询语句时,一定要遵循一定的原则才能能够使SQL语句执行起来更加的高效率。本文我们主要就总结了34条高性能SQL语句的原则,接下来就让我们一起来了解一下这部分内容吧。 在SQL...
  • 执行计划是数据库根据SQL语句和相关表的统计信息作出的一个查询方案,这个方案是由查询优化器自动分析产生的,比如一条SQL语句如果用来从一个 10万条记录的表中查1条记录,那查询优化器会选择“索引查找”方式,如果...
  • 写出高性能SQL语句

    2012-05-17 10:51:53
    写出高性能SQL语句的35条方法 整合简单,无关联的数据库访问、删除重复记录、选择最有效率的表名顺序等等
  • 90 再次重温写出各种SQL语句的时候,会用什么执行计划?(3).pdf
  • 89 再次重温写出各种SQL语句的时候,会用什么执行计划?(2).pdf
  • 88 再次重温写出各种SQL语句的时候,会用什么执行计划?(1).pdf
  • 执行计划是数据库根据SQL语句和相关表的统计信息作出的一个查询方案,这个方案是由查询优化器自动分析产生的,比如一条SQL语句如果用来从一个 10万条记录的表中查1条记录,那查询优化器会选择“索引查找”方式,如果...

    1、 首先要搞明白什么叫执行计划?

    执行计划是数据库根据SQL语句和相关表的统计信息作出的一个查询方案,这个方案是由查询优化器自动分析产生的,比如一条SQL语句如果用来从一个 10万条记录的表中查1条记录,那查询优化器会选择“索引查找”方式,如果该表进行了归档,当前只剩下5000条记录了,那查询优化器就会改变方案,采用 “全表扫描”方式。

    可见,执行计划并不是固定的,它是“个性化的”。产生一个正确的“执行计划”有两点很重要:

    (1) SQL语句是否清晰地告诉查询优化器它想干什么?

    (2) 查询优化器得到的数据库统计信息是否是最新的、正确的?

    2、 统一SQL语句的写法
    对于以下两句SQL语句,程序员认为是相同的,数据库查询优化器认为是不同的。

    select*from dual

    select*From dual
    其实就是大小写不同,查询分析器就认为是两句不同的SQL语句,必须进行两次解析。生成2个执行计划。所以作为程序员,应该保证相同的查询语句在任何地方都一致,多一个空格都不行!

    3、 不要把SQL语句写得太复杂

    我经常看到,从数据库中捕捉到的一条SQL语句打印出来有2张A4纸这么长。一般来说这么复杂的语句通常都是有问题的。我拿着这2页长的SQL语句去请教原作者,结果他说时间太长,他一时也看不懂了。可想而知,连原作者都有可能看糊涂的SQL语句,数据库也一样会看糊涂。

    一般,将一个Select语句的结果作为子集,然后从该子集中再进行查询,这种一层嵌套语句还是比较常见的,但是根据经验,超过3层嵌套,查询优化 器就很容易给出错误的执行计划。因为它被绕晕了。像这种类似人工智能的东西,终究比人的分辨力要差些,如果人都看晕了,我可以保证数据库也会晕的。

    另外,执行计划是可以被重用的,越简单的SQL语句被重用的可能性越高。而复杂的SQL语句只要有一个字符发生变化就必须重新解析,然后再把这一大堆垃圾塞在内存里。可想而知,数据库的效率会何等低下。

    4、 使用“临时表”暂存中间结果

    简化SQL语句的重要方法就是采用临时表暂存中间结果,但是,临时表的好处远远不止这些,将临时结果暂存在临时表,后面的查询就在tempdb中了,这可以避免程序中多次扫描主表,也大大减少了程序执行中“共享锁”阻塞“更新锁”,减少了阻塞,提高了并发性能。

    5、 OLTP系统SQL语句必须采用绑定变量

    selectfrom orderheader where changetime >‘2010-10-20 00:00:01’
    select
    from orderheader where changetime >‘2010-09-22 00:00:01’
    以上两句语句,查询优化器认为是不同的SQL语句,需要解析两次。如果采用绑定变量
    select*from orderheader where changetime >@chgtime

    @chgtime变量可以传入任何值,这样大量的类似查询可以重用该执行计划了,这可以大大降低数据库解析SQL语句的负担。一次解析,多次重用,是提高数据库效率的原则。

    6、 绑定变量窥测

    事物都存在两面性,绑定变量对大多数OLTP处理是适用的,但是也有例外。比如在where条件中的字段是“倾斜字段”的时候。

    “倾斜字段”指该列中的绝大多数的值都是相同的,比如一张人口调查表,其中“民族”这列,90%以上都是汉族。那么如果一个SQL语句要查询30岁的汉族人口有多少,那“民族”这列必然要被放在where条件中。这个时候如果采用绑定变量@nation会存在很大问题。

    试想如果@nation传入的第一个值是“汉族”,那整个执行计划必然会选择表扫描。然后,第二个值传入的是“布依族”,按理说“布依族”占的比例 可能只有万分之一,应该采用索引查找。但是,由于重用了第一次解析的“汉族”的那个执行计划,那么第二次也将采用表扫描方式。这个问题就是著名的“绑定变 量窥测”,建议对于“倾斜字段”不要采用绑定变量。

    7、 只在必要的情况下才使用begin tran

    SQL Server中一句SQL语句默认就是一个事务,在该语句执行完成后也是默认commit的。其实,这就是begin tran的一个最小化的形式,好比在每句语句开头隐含了一个begin tran,结束时隐含了一个commit。

    有些情况下,我们需要显式声明begin tran,比如做“插、删、改”操作需要同时修改几个表,要求要么几个表都修改成功,要么都不成功。begin tran 可以起到这样的作用,它可以把若干SQL语句套在一起执行,最后再一起commit。好处是保证了数据的一致性,但任何事情都不是完美无缺的。Begin tran付出的代价是在提交之前,所有SQL语句锁住的资源都不能释放,直到commit掉。

    可见,如果Begin tran套住的SQL语句太多,那数据库的性能就糟糕了。在该大事务提交之前,必然会阻塞别的语句,造成block很多。

    Begin tran使用的原则是,在保证数据一致性的前提下,begin tran 套住的SQL语句越少越好!有些情况下可以采用触发器同步数据,不一定要用begin tran。

    8、 一些SQL查询语句应加上nolock

    在SQL语句中加nolock是提高SQL Server并发性能的重要手段,在oracle中并不需要这样做,因为oracle的结构更为合理,有undo表空间保存“数据前影”,该数据如果在修 改中还未commit,那么你读到的是它修改之前的副本,该副本放在undo表空间中。这样,oracle的读、写可以做到互不影响,这也是oracle 广受称赞的地方。SQL Server 的读、写是会相互阻塞的,为了提高并发性能,对于一些查询,可以加上nolock,这样读的时候可以允许写,但缺点是可能读到未提交的脏数据。使用 nolock有3条原则。

    (1) 查询的结果用于“插、删、改”的不能加nolock !

    (2) 查询的表属于频繁发生页分裂的,慎用nolock !

    (3) 使用临时表一样可以保存“数据前影”,起到类似oracle的undo表空间的功能,

    能采用临时表提高并发性能的,不要用nolock 。

    9、 聚集索引没有建在表的顺序字段上,该表容易发生页分裂

    比如订单表,有订单编号orderid,也有客户编号contactid,那么聚集索引应该加在哪个字段上呢?对于该表,订单编号是顺序添加的,如 果在orderid上加聚集索引,新增的行都是添加在末尾,这样不容易经常产生页分裂。然而,由于大多数查询都是根据客户编号来查的,因此,将聚集索引加 在contactid上才有意义。而contactid对于订单表而言,并非顺序字段。

    比如“张三”的“contactid”是001,那么“张三”的订单信息必须都放在这张表的第一个数据页上,如果今天“张三”新下了一个订单,那该订单信息不能放在表的最后一页,而是第一页!如果第一页放满了呢?很抱歉,该表所有数据都要往后移动为这条记录腾地方。

    SQL Server的索引和Oracle的索引是不同的,SQL Server的聚集索引实际上是对表按照聚集索引字段的顺序进行了排序,相当于oracle的索引组织表。SQL Server的聚集索引就是表本身的一种组织形式,所以它的效率是非常高的。也正因为此,插入一条记录,它的位置不是随便放的,而是要按照顺序放在该放的 数据页,如果那个数据页没有空间了,就引起了页分裂。所以很显然,聚集索引没有建在表的顺序字段上,该表容易发生页分裂。

    曾经碰到过一个情况,一位哥们的某张表重建索引后,插入的效率大幅下降了。估计情况大概是这样的。该表的聚集索引可能没有建在表的顺序字段上,该表 经常被归档,所以该表的数据是以一种稀疏状态存在的。比如张三下过20张订单,而最近3个月的订单只有5张,归档策略是保留3个月数据,那么张三过去的 15张订单已经被归档,留下15个空位,可以在insert发生时重新被利用。在这种情况下由于有空位可以利用,就不会发生页分裂。但是查询性能会比较 低,因为查询时必须扫描那些没有数据的空位。

    重建聚集索引后情况改变了,因为重建聚集索引就是把表中的数据重新排列一遍,原来的空位没有了,而页的填充率又很高,插入数据经常要发生页分裂,所以性能大幅下降。

    对于聚集索引没有建在顺序字段上的表,是否要给与比较低的页填充率?是否要避免重建聚集索引?是一个值得考虑的问题!

    10、加nolock后查询经常发生页分裂的表,容易产生跳读或重复读

    加nolock后可以在“插、删、改”的同时进行查询,但是由于同时发生“插、删、改”,在某些情况下,一旦该数据页满了,那么页分裂不可避免,而 此时nolock的查询正在发生,比如在第100页已经读过的记录,可能会因为页分裂而分到第101页,这有可能使得nolock查询在读101页时重复 读到该条数据,产生“重复读”。同理,如果在100页上的数据还没被读到就分到99页去了,那nolock查询有可能会漏过该记录,产生“跳读”。

    上面提到的哥们,在加了nolock后一些操作出现报错,估计有可能因为nolock查询产生了重复读,2条相同的记录去插入别的表,当然会发生主键冲突。

    11、使用like进行模糊查询时应注意

    有的时候会需要进行一些模糊查询比如
    select*from contact where username like ‘%yue%’

    关键词%yue%,由于yue前面用到了“%”,因此该查询必然走全表扫描,除非必要,否则不要在关键词前加%,

    12、数据类型的隐式转换对查询效率的影响

    sql server2000的数据库,我们的程序在提交sql语句的时候,没有使用强类型提交这个字段的值,由sql server 2000自动转换数据类型,会导致传入的参数与主键字段类型不一致,这个时候sql server 2000可能就会使用全表扫描。Sql2005上没有发现这种问题,但是还是应该注意一下。

    13、SQL Server 表连接的三种方式

    (1) Merge Join

    (2) Nested Loop Join

    (3) Hash Join

    SQL Server 2000只有一种join方式——Nested Loop Join,如果A结果集较小,那就默认作为外表,A中每条记录都要去B中扫描一遍,实际扫过的行数相当于A结果集行数x B结果集行数。所以如果两个结果集都很大,那Join的结果很糟糕。

    SQL Server 2005新增了Merge Join,如果A表和B表的连接字段正好是聚集索引所在字段,那么表的顺序已经排好,只要两边拼上去就行了,这种join的开销相当于A表的结果集行数加 上B表的结果集行数,一个是加,一个是乘,可见merge join 的效果要比Nested Loop Join好多了。

    如果连接的字段上没有索引,那SQL2000的效率是相当低的,而SQL2005提供了Hash join,相当于临时给A,B表的结果集加上索引,因此SQL2005的效率比SQL2000有很大提高,我认为,这是一个重要的原因。

    总结一下,在表连接时要注意以下几点:

    (1) 连接字段尽量选择聚集索引所在的字段

    (2) 仔细考虑where条件,尽量减小A、B表的结果集

    (3) 如果很多join的连接字段都缺少索引,而你还在用SQL Server 2000,赶紧升级吧。

    如何为数据库添加索引:
    为方便讲述,我们先建立一个如下的表。

    CREATE TABLE mytable (
         id serial primary key,
         category_id int not null default 0,
         user_id int not null default 0,
         adddate int not null default 0
      );

    很简单吧,不过对于要说明这个问题,已经足够了。如果你在查询时常用类似以下的语句:

    SELECT * FROM mytable WHERE category_id=1;

    最直接的应对之道,是为category_id建立一个简单的索引:

    CREATE INDEX mytable_categoryid
         ON mytable (category_id);

    OK,搞定?先别高兴,如果你有不止一个选择条件呢?例如:

    SELECT * FROM mytable WHERE category_id=1 AND user_id=2;

    你的第一反应可能是,再给user_id建立一个索引。不好,这不是一个最佳的方法。你可以建立多重的索引。

    CREATE INDEX mytable_categoryid_userid ON mytable (category_id,user_id);

    注意到我在命名时的习惯了吗?我使用"表名_字段1名_字段2名"的方式。你很快就会知道我为什么这样做了。

    现在你已经为适当的字段建立了索引,不过,还是有点不放心吧,你可能会问,数据库会真正用到这些索引吗?测试一下就OK,对于大多数的数据库来说,这是很容易的,只要使用EXPLAIN命令:

    EXPLAIN

    SELECT * FROM mytable
        WHERE category_id=1 AND user_id=2;

    This is what Postgres 7.1 returns (exactly as I expected)

    NOTICE: QUERY PLAN:

    Index Scan using mytable_categoryid_userid on
         mytable (cost=0.00…2.02 rows=1 width=16)

    EXPLAIN

    以上是postgres的数据,可以看到该数据库在查询的时候使用了一个索引(一个好开始),而且它使用的是我创建的第二个索引。看到我上面命名的好处了吧,你马上知道它使用适当的索引了。

    接着,来个稍微复杂一点的,如果有个ORDER BY字句呢?不管你信不信,大多数的数据库在使用order by的时候,都将会从索引中受益。

    SELECT * FROM mytable
        WHERE category_id=1 AND user_id=2
         ORDER BY adddate DESC;

    有点迷惑了吧?很简单,就象为where字句中的字段建立一个索引一样,也为ORDER BY的字句中的字段建立一个索引:

    CREATE INDEX mytable_categoryid_userid_adddate
         ON mytable (category_id,user_id,adddate);

    注意: “mytable_categoryid_userid_adddate” 将会被截短为

    “mytable_categoryid_userid_addda”

    CREATE

    EXPLAIN SELECT * FROM mytable
        WHERE category_id=1 AND user_id=2
         ORDER BY adddate DESC;

    NOTICE: QUERY PLAN:

    Sort (cost=2.03…2.03 rows=1 width=16)
        -> Index Scan using mytable_categoryid_userid_addda
           on mytable (cost=0.00…2.02 rows=1 width=16)

    EXPLAIN

    看看EXPLAIN的输出,好象有点恐怖啊,数据库多做了一个我们没有要求的排序,这下知道性能如何受损了吧,看来我们对于数据库的自身运作是有点过于乐观了,那么,给数据库多一点提示吧。

    为了跳过排序这一步,我们并不需要其它另外的索引,只要将查询语句稍微改一下。这里用的是postgres,我们将给该数据库一个额外的提示–在ORDER BY语句中,加入where语句中的字段。这只是一个技术上的处理,并不是必须的,因为实际上在另外两个字段上,并不会有任何的排序操作,不过如果加入,postgres将会知道哪些是它应该做的。

    EXPLAIN SELECT * FROM mytable
        WHERE category_id=1 AND user_id=2
         ORDER BY category_id DESC,user_id DESC,adddate DESC;

    NOTICE: QUERY PLAN:

    Index Scan Backward using
        mytable_categoryid_userid_addda on mytable
         (cost=0.00…2.02 rows=1 width=16)

    EXPLAIN

    现在使用我们料想的索引了,而且它还挺聪明,知道可以从索引后面开始读,从而避免了任何的排序。

    以上说得细了一点,不过如果你的数据库非常巨大,并且每日的页面请求达上百万算,我想你会获益良多的。不过,如果你要做更为复杂的查询呢,例如将多张表结合起来查询,特别是where限制字句中的字段是来自不止一个表格时,应该怎样处理呢?我通常都尽量避免这种做法,因为这样数据库要将各个表中的东西都结合起来,然后再排除那些不合适的行,搞不好开销会很大。

    如果不能避免,你应该查看每张要结合起来的表,并且使用以上的策略来建立索引,然后再用EXPLAIN命令验证一下是否使用了你料想中的索引。如果是的话,就OK。不是的话,你可能要建立临时的表来将他们结合在一起,并且使用适当的索引。

    要注意的是,建立太多的索引将会影响更新和插入的速度,因为它需要同样更新每个索引文件。对于一个经常需要更新和插入的表格,就没有必要为一个很少使用的where字句单独建立索引了,对于比较小的表,排序的开销不会很大,也没有必要建立另外的索引。

    以上介绍的只是一些十分基本的东西,其实里面的学问也不少,单凭EXPLAIN我们是不能判定该方法是否就是最优化的,每个数据库都有自己的一些优化器,虽然可能还不太完善,但是它们都会在查询时对比过哪种方式较快,在某些情况下,建立索引的话也未必会快,例如索引放在一个不连续的存储空间时,这会增加读磁盘的负担,因此,哪个是最优,应该通过实际的使用环境来检验。

    在刚开始的时候,如果表不大,没有必要作索引,我的意见是在需要的时候才作索引,也可用一些命令来优化表,例如MySQL可用"OPTIMIZE TABLE"。

    展开全文
  • 行业-90 再次重温写出各种SQL语句的时候,会用什么执行计划?(3).rar
  • 行业-89 再次重温写出各种SQL语句的时候,会用什么执行计划?(2).rar
  • 行业-88 再次重温写出各种SQL语句的时候,会用什么执行计划?(1).rar
  • 对于数据库中的一个表,需要执行的sql语句特别特别多,且语句都是相同的情况下,将数据库表导出Excel格式,写好一条语句,然后一句公式获取对应的值,写好一条语句,将鼠标放在语句单元格的右下角下拉即可,然后可...

    对于数据库中的一个表,需要执行的sql语句特别特别多,且语句都是相同的情况下,将数据库表导出Excel格式,写好一条语句,然后写一句公式获取对应的值,写好一条语句,将鼠标放在语句单元格的右下角下拉即可,然后可将所有的语句复制粘贴出去执行


    • 感谢您的阅读。如果感觉文章对您有用,麻烦您动动手指点个赞,以资鼓励。谢谢!

    展开全文
  • AQL语句和SQL语句对比,快速写出AQL语句地址 https://www.arangodb.com/why-arangodb/sql-aql-comparison/

    AQL语句和SQL语句对比,快速写出AQL语句地址

    https://www.arangodb.com/why-arangodb/sql-aql-comparison/

    展开全文
  • 写出高性能SQL语句的35条方法! 实用,好用,实在! 写出高性能SQL语句的35条方法! 写出高性能SQL语句的35条方法!
  • 高性能的SQL语句能提高页面的执行效率,让你的服务器运行的更为流畅,所以大家在以后的使用过程中,尽量的考虑到效率。
  • 执行计划是数据库根据SQL语句和相关表的统计信息作出的一个查询方案,这个方案是由查询优化器自动分析产生的,比如一条SQL语句如果用来从一个 10万条记录的表中查1条记录,那查询优化器会选择“索引查找”方式,如果...

    1、 首先要搞明白什么叫执行计划?

    执行计划是数据库根据SQL语句和相关表的统计信息作出的一个查询方案,这个方案是由查询优化器自动分析产生的,比如一条SQL语句如果用来从一个 10万条记录的表中查1条记录,那查询优化器会选择“索引查找”方式,如果该表进行了归档,当前只剩下5000条记录了,那查询优化器就会改变方案,采用 “全表扫描”方式。

    可见,执行计划并不是固定的,它是“个性化的”。产生一个正确的“执行计划”有两点很重要:

    (1)    SQL语句是否清晰地告诉查询优化器它想干什么?

    (2)    查询优化器得到的数据库统计信息是否是最新的、正确的?


    2、 统一SQL语句的写法

    对于以下两句SQL语句,程序员认为是相同的,数据库查询优化器认为是不同的。 

    select*from dual

    select*From dual

     

    其实就是大小写不同,查询分析器就认为是两句不同的SQL语句,必须进行两次解析。生成2个执行计划。所以作为程序员,应该保证相同的查询语句在任何地方都一致,多一个空格都不行!

    3、 不要把SQL语句写得太复杂

    我经常看到,从数据库中捕捉到的一条SQL语句打印出来有2张A4纸这么长。一般来说这么复杂的语句通常都是有问题的。我拿着这2页长的SQL语句去请教原作者,结果他说时间太长,他一时也看不懂了。可想而知,连原作者都有可能看糊涂的SQL语句,数据库也一样会看糊涂。

    一般,将一个Select语句的结果作为子集,然后从该子集中再进行查询,这种一层嵌套语句还是比较常见的,但是根据经验,超过3层嵌套,查询优化器就很容易给出错误的执行计划。因为它被绕晕了。像这种类似人工智能的东西,终究比人的分辨力要差些,如果人都看晕了,我可以保证数据库也会晕的。

    另外,执行计划是可以被重用的,越简单的SQL语句被重用的可能性越高。而复杂的SQL语句只要有一个字符发生变化就必须重新解析,然后再把这一大堆垃圾塞在内存里。可想而知,数据库的效率会何等低下。

    4、 使用“临时表”暂存中间结果

    简化SQL语句的重要方法就是采用临时表暂存中间结果,但是,临时表的好处远远不止这些,将临时结果暂存在临时表,后面的查询就在tempdb中了,这可以避免程序中多次扫描主表,也大大减少了程序执行中“共享锁”阻塞“更新锁”,减少了阻塞,提高了并发性能。

    5、 OLTP系统SQL语句必须采用绑定变量 

    select*from orderheaderwhere changetime>'2010-10-20 00:00:01'
    select*from orderheaderwhere changetime>'2010-09-22 00:00:01'


     

    以上两句语句,查询优化器认为是不同的SQL语句,需要解析两次。如果采用绑定变量

    select*from orderheaderwhere changetime>@chgtime

    @chgtime变量可以传入任何值,这样大量的类似查询可以重用该执行计划了,这可以大大降低数据库解析SQL语句的负担。一次解析,多次重用,是提高数据库效率的原则。

    6、 绑定变量窥测

    事物都存在两面性,绑定变量对大多数OLTP处理是适用的,但是也有例外。比如在where条件中的字段是“倾斜字段”的时候。

    “倾斜字段”指该列中的绝大多数的值都是相同的,比如一张人口调查表,其中“民族”这列,90%以上都是汉族。那么如果一个SQL语句要查询30岁的汉族人口有多少,那“民族”这列必然要被放在where条件中。这个时候如果采用绑定变量@nation会存在很大问题。

    试想如果@nation传入的第一个值是“汉族”,那整个执行计划必然会选择表扫描。然后,第二个值传入的是“布依族”,按理说“布依族”占的比例可能只有万分之一,应该采用索引查找。但是,由于重用了第一次解析的“汉族”的那个执行计划,那么第二次也将采用表扫描方式。这个问题就是著名的“绑定变量窥测”,建议对于“倾斜字段”不要采用绑定变量。

    7、 只在必要的情况下才使用begin tran

    SQL Server中一句SQL语句默认就是一个事务,在该语句执行完成后也是默认commit的。其实,这就是begin tran的一个最小化的形式,好比在每句语句开头隐含了一个begin tran,结束时隐含了一个commit。

    有些情况下,我们需要显式声明begin tran,比如做“插、删、改”操作需要同时修改几个表,要求要么几个表都修改成功,要么都不成功。begin tran 可以起到这样的作用,它可以把若干SQL语句套在一起执行,最后再一起commit。好处是保证了数据的一致性,但任何事情都不是完美无缺的。Begin tran付出的代价是在提交之前,所有SQL语句锁住的资源都不能释放,直到commit掉。

    可见,如果Begin tran套住的SQL语句太多,那数据库的性能就糟糕了。在该大事务提交之前,必然会阻塞别的语句,造成block很多。

    Begin tran使用的原则是,在保证数据一致性的前提下,begin tran 套住的SQL语句越少越好!有些情况下可以采用触发器同步数据,不一定要用begin tran。

    8、 一些SQL查询语句应加上nolock

    在SQL语句中加nolock是提高SQL Server并发性能的重要手段,在oracle中并不需要这样做,因为oracle的结构更为合理,有undo表空间保存“数据前影”,该数据如果在修改中还未commit,那么你读到的是它修改之前的副本,该副本放在undo表空间中。这样,oracle的读、写可以做到互不影响,这也是oracle 广受称赞的地方。SQL Server 的读、写是会相互阻塞的,为了提高并发性能,对于一些查询,可以加上nolock,这样读的时候可以允许写,但缺点是可能读到未提交的脏数据。使用 nolock有3条原则。

    (1)    查询的结果用于“插、删、改”的不能加nolock !

    (2)    查询的表属于频繁发生页分裂的,慎用nolock !

    (3)    使用临时表一样可以保存“数据前影”,起到类似oracle的undo表空间的功能,

    能采用临时表提高并发性能的,不要用nolock 。

    9、 聚集索引没有建在表的顺序字段上,该表容易发生页分裂

    比如订单表,有订单编号orderid,也有客户编号contactid,那么聚集索引应该加在哪个字段上呢?对于该表,订单编号是顺序添加的,如果在orderid上加聚集索引,新增的行都是添加在末尾,这样不容易经常产生页分裂。然而,由于大多数查询都是根据客户编号来查的,因此,将聚集索引加在contactid上才有意义。而contactid对于订单表而言,并非顺序字段。

    比如“张三”的“contactid”是001,那么“张三”的订单信息必须都放在这张表的第一个数据页上,如果今天“张三”新下了一个订单,那该订单信息不能放在表的最后一页,而是第一页!如果第一页放满了呢?很抱歉,该表所有数据都要往后移动为这条记录腾地方。

    SQL Server的索引和Oracle的索引是不同的,SQL Server的聚集索引实际上是对表按照聚集索引字段的顺序进行了排序,相当于oracle的索引组织表。SQL Server的聚集索引就是表本身的一种组织形式,所以它的效率是非常高的。也正因为此,插入一条记录,它的位置不是随便放的,而是要按照顺序放在该放的数据页,如果那个数据页没有空间了,就引起了页分裂。所以很显然,聚集索引没有建在表的顺序字段上,该表容易发生页分裂。

    曾经碰到过一个情况,一位哥们的某张表重建索引后,插入的效率大幅下降了。估计情况大概是这样的。该表的聚集索引可能没有建在表的顺序字段上,该表经常被归档,所以该表的数据是以一种稀疏状态存在的。比如张三下过20张订单,而最近3个月的订单只有5张,归档策略是保留3个月数据,那么张三过去的 15张订单已经被归档,留下15个空位,可以在insert发生时重新被利用。在这种情况下由于有空位可以利用,就不会发生页分裂。但是查询性能会比较低,因为查询时必须扫描那些没有数据的空位。

    重建聚集索引后情况改变了,因为重建聚集索引就是把表中的数据重新排列一遍,原来的空位没有了,而页的填充率又很高,插入数据经常要发生页分裂,所以性能大幅下降。

    对于聚集索引没有建在顺序字段上的表,是否要给与比较低的页填充率?是否要避免重建聚集索引?是一个值得考虑的问题!

    10、加nolock后查询经常发生页分裂的表,容易产生跳读或重复读

    加nolock后可以在“插、删、改”的同时进行查询,但是由于同时发生“插、删、改”,在某些情况下,一旦该数据页满了,那么页分裂不可避免,而此时nolock的查询正在发生,比如在第100页已经读过的记录,可能会因为页分裂而分到第101页,这有可能使得nolock查询在读101页时重复读到该条数据,产生“重复读”。同理,如果在100页上的数据还没被读到就分到99页去了,那nolock查询有可能会漏过该记录,产生“跳读”。

    上面提到的哥们,在加了nolock后一些操作出现报错,估计有可能因为nolock查询产生了重复读,2条相同的记录去插入别的表,当然会发生主键冲突。

    11、使用like进行模糊查询时应注意

    有的时候会需要进行一些模糊查询比如

    select*from contactwhere usernamelike%yue%

     

    关键词%yue%,由于yue前面用到了“%”,因此该查询必然走全表扫描,除非必要,否则不要在关键词前加%,

    12、数据类型的隐式转换对查询效率的影响

    sql server2000的数据库,我们的程序在提交sql语句的时候,没有使用强类型提交这个字段的值,由sql server 2000自动转换数据类型,会导致传入的参数与主键字段类型不一致,这个时候sql server 2000可能就会使用全表扫描。Sql2005上没有发现这种问题,但是还是应该注意一下。

    13、SQL Server 表连接的三种方式

    (1) Merge Join

    (2) Nested Loop Join

    (3) Hash Join

    SQL Server 2000只有一种join方式——Nested Loop Join,如果A结果集较小,那就默认作为外表,A中每条记录都要去B中扫描一遍,实际扫过的行数相当于A结果集行数x B结果集行数。所以如果两个结果集都很大,那Join的结果很糟糕。

    SQL Server 2005新增了Merge Join,如果A表和B表的连接字段正好是聚集索引所在字段,那么表的顺序已经排好,只要两边拼上去就行了,这种join的开销相当于A表的结果集行数加上B表的结果集行数,一个是加,一个是乘,可见merge join 的效果要比Nested Loop Join好多了。

    如果连接的字段上没有索引,那SQL2000的效率是相当低的,而SQL2005提供了Hash join,相当于临时给A,B表的结果集加上索引,因此SQL2005的效率比SQL2000有很大提高,我认为,这是一个重要的原因。

    总结一下,在表连接时要注意以下几点:

    (1)    连接字段尽量选择聚集索引所在的字段

    (2)    仔细考虑where条件,尽量减小A、B表的结果集

    (3)    如果很多join的连接字段都缺少索引,而你还在用SQL Server 2000,赶紧升级吧。

    以上内容来自链接:http://www.cnblogs.com/ATree/archive/2011/02/13/sql_optimize_1.html

    展开全文
  • 写SQL语句的一些建议
  • Laravel ORM的语句怎么打印原生Sql语句  ORM有诸般好处,但刚接触Laravel的新手在不熟悉的情况下无法判断自己的ORM语句是否正确,这个时候就需要将ORM的语句打印成原生Sql语句。  Laravel Builder类中有...
  • 如何写出高性能SQL语句

    千次阅读 2013-11-15 11:19:55
    优化SQL查询:如何写出高性能SQL语句 1、首先要搞明白什么叫执行计划?  执行计划是数据库根据SQL语句和相关表的统计信息作出的一个查询方案,这个方案是由查询优化器自动分析产生欀如一条SQL语句如果用来从一个10...
  • 如何写出复杂业务查询的sql语句

    千次阅读 2018-03-16 15:01:41
    如何写出复杂业务查询的sql语句如何写出复杂的sql语句:首先要建立一个概念,复杂的sql语句也是最基本的sql语句连接而成,所以最重要的是先要理清思路和逻辑,弄清自己要查哪几张表,要用哪几个字段,表之间如何关联...
  • Mysql写出高质量的sql语句的几点建议

    千次阅读 2015-06-03 09:50:48
    CleverCode在实际的工作也过一些低效率的sql语句。这些语句会给数据库带来很大的压力,最主要的表现就是sql语句运行慢,后来逐渐的去优化和尝试。总结了一些高质量的sql语句的写法。这里CleverCode总结一下分享给...
  • 非常的教程,对自己的SQL编程习惯有好处。
  • 上海交大网校Oracle作业二--写出SQL语句
  • 书写高质量SQL的30条建议,如何写出高性能的SQL语句源码
  • 如何写出高效率的SQL语句。看看SQL优化技巧吧
  • 在笔试中一般都会碰到书写sql语句的题目,上次去面试就碰到了,所以在这里总结一些。 创建表语句 SET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOSET ANSI_PADDING ONGOCREATE TABLE [dbo].[stuscore] ( [name] ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 379,567
精华内容 151,826
关键字:

怎样写出好的sql语句