목차
什么是执行计划?执行计划是依赖于什么信息。
统一SQL语句的写法减少解析开销
减少SQL语句的嵌套
使用“临时表”暂存中间结果
OLTP系统SQL语句必须采用绑定变量
倾斜字段的绑定变量窥测问题
begin tran的事务要尽量地小
一些SQL查询语句应加上nolock
加nolock后查询经常发生页分裂的表,容易产生跳读或重复读
聚集索引没有建在表的顺序字段上,该表容易发生页分裂
使用复合索引提高多个where条件的查询速度
使用like进行模糊查询时应注意尽量不要使用前%
SQL Server 表连接的三种方式
Row_number 会导致表扫描,用临时表分页更好
其他
데이터 베이스 MySQL 튜토리얼 一个十几年经验DBA的宝贵经验财富

一个十几年经验DBA的宝贵经验财富

Jun 07, 2016 pm 04:24 PM
dba 무엇 구현하다 경험 재산

什么是执行计划?执行计划是依赖于什么信息。 执行计划是数据库根据SQL语句和相关表的统计信息作出的一个查询方案,这个方案是由查询优化器自动分析产生的,比如一条SQL语句如果用来从一个10万条记录的表中查1条记录,那查询优化器会选择“索引查找”方式,

什么是执行计划?执行计划是依赖于什么信息。

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

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

  • SQL语句是否清晰地告诉查询优化器它想干什么?
  • 查询优化器得到的数据库统计信息是否是最新的、正确的?

统一SQL语句的写法减少解析开销

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

select * from dual
SELECT * FROM dual
로그인 후 복사

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

减少SQL语句的嵌套

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

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

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

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

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

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

select * from 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语句的负担。一次解析,多次重用,是提高数据库效率的原则。

倾斜字段的绑定变量窥测问题

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

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

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

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。

一些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 。

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

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

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

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

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

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

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

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

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

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

使用复合索引提高多个where条件的查询速度

复合索引通常拥有比单一索引更好的选择性。而且,它是特别针对某个where条件所设立的索引,它已经进行了排序,所以查询速度比单索引更快。复合索引的引导字段必须采用“选择性高”的字段。比如有3个字段:日期,性别,年龄。大家看,应该采用哪个字段作引导字段?显然应该采用“日期”作为引导字段。日期是3个字段中选择性最高的字段。

这里有一个例外,如果日期同时也是聚集索引的引导字段,可以不建复合索引,直接走聚集索引,效率也是比较高的。

不要把聚集索引建成“复合索引”,聚集索引越简单越好,选择性越高越好!聚集索引包括2个字段尚可容忍。但是超过2个字段,应该考虑建1个自增字段作为主键,聚集索引可以不做主键。

使用like进行模糊查询时应注意尽量不要使用前%

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

Select * from nowamagic where username like ‘%gonn%’
로그인 후 복사

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

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的连接字段都缺少索引,而你还在用SQL2000,干紧升级吧。

Row_number 会导致表扫描,用临时表分页更好

ROW_Number分页的测试结果:

  • 使用ROW_Number来分页:CPU 时间= 317265 毫秒,占用时间= 423090 毫秒
  • 使用临时表来分页:CPU 时间= 1266 毫秒,占用时间= 6705 毫秒

ROW_Number实现是基于order by的,排序对查询的影响显而易见。

其他

诸如有的写法会限制使用索引

Select * from tablename where chgdate +7 < sysdate

Select * from tablename where chgdate < sysdate -7
로그인 후 복사
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

AI Hentai Generator

AI Hentai Generator

AI Hentai를 무료로 생성하십시오.

인기 기사

R.E.P.O. 에너지 결정과 그들이하는 일 (노란색 크리스탈)
3 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. 최고의 그래픽 설정
3 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. 아무도들을 수없는 경우 오디오를 수정하는 방법
3 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25 : Myrise에서 모든 것을 잠금 해제하는 방법
4 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌

뜨거운 도구

메모장++7.3.1

메모장++7.3.1

사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전

SublimeText3 중국어 버전

중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기

스튜디오 13.0.1 보내기

강력한 PHP 통합 개발 환경

드림위버 CS6

드림위버 CS6

시각적 웹 개발 도구

SublimeText3 Mac 버전

SublimeText3 Mac 버전

신 수준의 코드 편집 소프트웨어(SublimeText3)

5분마다 실행되는 Python 스크립트 5분마다 실행되는 Python 스크립트 Sep 10, 2023 pm 03:33 PM

자동화 및 작업 스케줄링은 소프트웨어 개발에서 반복적인 작업을 간소화하는 데 중요한 역할을 합니다. API에서 데이터 가져오기, 데이터 처리 수행, 주기적인 업데이트 보내기 등 5분마다 실행해야 하는 Python 스크립트가 있다고 상상해 보세요. 스크립트를 너무 자주 수동으로 실행하면 시간이 많이 걸리고 오류가 발생하기 쉽습니다. 여기서 작업 스케줄링이 시작됩니다. 이 블로그 게시물에서는 Python 스크립트가 5분마다 실행되도록 예약하여 수동 개입 없이 자동으로 실행되도록 하는 방법을 살펴보겠습니다. 이 목표를 달성하는 데 사용할 수 있는 다양한 방법과 라이브러리에 대해 논의하여 작업을 효율적으로 자동화할 수 있습니다. time.sleep() 함수를 사용하여 5분마다 Python 스크립트를 실행하는 쉬운 방법은 tim을 활용하는 것입니다.

GIGABYTE 마더보드에서 키보드 부팅 기능을 설정하는 방법(GIGABYTE 마더보드에서 키보드 부팅 모드 활성화) GIGABYTE 마더보드에서 키보드 부팅 기능을 설정하는 방법(GIGABYTE 마더보드에서 키보드 부팅 모드 활성화) Dec 31, 2023 pm 05:15 PM

Gigabyte 마더보드에서 키보드 시작을 설정하는 방법 먼저, 키보드 시작을 지원해야 한다면 PS2 키보드여야 합니다! ! 설정 단계는 다음과 같습니다. 1단계: 부팅 후 Del 또는 F2를 눌러 BIOS에 들어가고, BIOS의 고급(Advanced) 모드로 들어갑니다. 일반 마더보드는 기본적으로 마더보드의 EZ(Easy) 모드로 들어갑니다. F7을 눌러 고급 모드로 전환합니다. ROG 시리즈 마더보드는 기본적으로 BIOS로 들어갑니다. 고급 모드(간체 중국어를 사용하여 설명) 2단계: - [고급] - [고급 전원 관리(APM)]를 선택합니다. [PS2 키보드로 깨우기] 옵션 찾기 4단계: 이 옵션 기본값은 비활성화입니다. 아래로 당기면 세 가지 다른 설정 옵션이 표시됩니다. 즉, 컴퓨터를 켜려면 [스페이스바]를 누르고 그룹을 누르세요.

i7 3770에 가장 적합한 그래픽 카드는 무엇입니까? i7 3770에 가장 적합한 그래픽 카드는 무엇입니까? Dec 29, 2023 am 09:12 AM

Core i73770에 적합한 그래픽 카드는 무엇입니까? RTX3070은 뛰어난 성능과 첨단 기술을 갖춘 매우 강력한 그래픽 카드입니다. 게임을 하든, 그래픽을 렌더링하든, 기계 학습을 수행하든 RTX3070은 이를 쉽게 처리할 수 있습니다. NVIDIA의 Ampere 아키텍처를 사용하고 5888개의 CUDA 코어와 8GB의 GDDR6 메모리를 갖추고 있어 원활한 게임 경험과 고품질 그래픽 효과를 제공할 수 있습니다. RTX3070은 사실적인 빛과 그림자 효과를 표현할 수 있는 레이 트레이싱 기술도 지원합니다. 전체적으로 RTX3070은 고성능과 고품질을 추구하는 사람들에게 적합한 강력하고 진보된 그래픽 카드입니다. RTX3070은 NVIDIA 시리즈 그래픽 카드입니다. 2세대 NVID 사용

Linux에서 스크립팅 및 실행을 위해 Python을 사용하는 방법 Linux에서 스크립팅 및 실행을 위해 Python을 사용하는 방법 Oct 05, 2023 am 11:45 AM

Linux에서 Python을 사용하여 스크립트를 작성하고 실행하는 방법 Linux 운영 체제에서는 Python을 사용하여 다양한 스크립트를 작성하고 실행할 수 있습니다. Python은 스크립팅을 보다 쉽고 효율적으로 만들기 위한 풍부한 라이브러리와 도구를 제공하는 간결하고 강력한 프로그래밍 언어입니다. 아래에서는 Linux에서 스크립트 작성 및 실행을 위해 Python을 사용하는 방법의 기본 단계를 소개하고, Python을 더 잘 이해하고 사용하는 데 도움이 되는 몇 가지 구체적인 코드 예제를 제공합니다. 파이썬 설치

음악 학생에게 적합한 태블릿 선택 음악 학생에게 적합한 태블릿 선택 Jan 10, 2024 pm 10:09 PM

뮤지션에게 적합한 태블릿은? 화웨이 아이패드에 탑재된 12.9인치 스피커는 아주 좋은 제품이다. 4개의 스피커가 탑재되어 있으며 사운드도 훌륭합니다. 게다가 프로 시리즈에 속해 다른 스타일보다 조금 더 나은 모습을 보여준다. 전체적으로 아이패드 프로는 매우 좋은 제품입니다. 이 mini4 휴대폰의 스피커는 작고 효과는 평균입니다. 외부에서 음악을 재생하는 데 사용할 수 없으며 음악을 즐기려면 헤드폰을 사용해야 합니다. 음질이 좋은 헤드폰은 효과가 약간 더 좋지만 30~40위안의 값싼 헤드폰은 요구 사항을 충족할 수 없습니다. 전자피아노 음악을 들으려면 어떤 태블릿을 사용해야 할까요? 10인치보다 큰 아이패드를 구매하고 싶다면 헨레(Henle)와 피아스코어(Piascore)라는 두 가지 애플리케이션을 사용하는 것이 좋습니다. 헨레 제공

RX580에 맞는 드라이버 버전을 선택하세요 RX580에 맞는 드라이버 버전을 선택하세요 Dec 29, 2023 pm 05:34 PM

rx5808g에 설치하는 것이 좋은 드라이버는 무엇입니까? 20.5.1 및 20.4.2WHQL은 소프트웨어 또는 드라이버의 버전 번호를 나타냅니다. 이러한 버전 번호는 일반적으로 소프트웨어나 드라이버에 대한 업데이트나 수정 사항을 식별하는 데 사용됩니다. 컴퓨터 세계에서 WHQL은 Windows Hardware Quality Labs의 약자로 Microsoft가 하드웨어 및 드라이버의 호환성과 안정성을 테스트하고 확인하는 데 사용하는 기관입니다. 따라서 20.5.1 및 20.4.2WHQL은 이러한 소프트웨어 또는 드라이버가 Microsoft의 테스트 및 검증을 통과했으며 Windows 운영 체제에서 안전하게 사용할 수 있음을 나타냅니다. AMDrx580 그래픽 카드는 상대적으로 안정적인 드라이버 20.5.1 및 20.4.2WHQL은 소프트웨어 또는 드라이버의 버전 번호를 나타냅니다. 이 버전 번호가 전달되었습니다.

코타나의 기능은 무엇입니까? 코타나의 기능은 무엇입니까? Jan 15, 2024 pm 10:15 PM

마이크로소프트가 개발한 윈도우 10 운영체제를 사용하는 과정에서 많은 사용자들이 코타나(Cortana)라는 신기술에 대해 궁금해하고 혼란스러워한다. 10 시스템. 인공지능(AIassistant) 서비스 프로그램. 자주 묻는 질문 및 해결 방법 Cortana에 검색 상자를 넣는 방법은 무엇입니까? 답변: "Cortana" Microsoft가 신중하게 구축한 클라우드 플랫폼 개인 지능형 비서입니다. 로그인 및 비로그인이라는 두 가지 사용 모드가 있습니다. 로그인한 경우

i34150 및 1G 독립 그래픽으로 플레이하기에 적합한 게임은 무엇입니까(i34150에 적합한 게임은 무엇입니까) i34150 및 1G 독립 그래픽으로 플레이하기에 적합한 게임은 무엇입니까(i34150에 적합한 게임은 무엇입니까) Jan 05, 2024 pm 08:24 PM

1G 독립 그래픽을 탑재한 i34150으로 어떤 게임을 할 수 있나요? LoL 같은 소규모 게임도 할 수 있나요? GTX750 및 GTX750TI는 매우 적합한 그래픽 카드 선택입니다. 작은 게임만 하거나 게임을 하지 않는다면 i34150 통합 그래픽 카드를 사용하는 것이 좋습니다. 일반적으로 그래픽 카드와 프로세서의 가격 차이는 그리 크지 않기 때문에 합리적인 조합을 선택하는 것이 중요합니다. 2G의 비디오 메모리가 필요한 경우 GTX750TI를 선택하는 것이 좋습니다. 1G의 비디오 메모리만 필요한 경우 GTX750을 선택하면 됩니다. GTX750TI는 오버클럭 기능을 갖춘 GTX750의 향상된 버전으로 볼 수 있습니다. i34150과 페어링할 수 있는 그래픽 카드는 필요에 따라 다릅니다. 독립형 게임을 플레이할 계획이라면 그래픽 카드 변경을 고려하는 것이 좋습니다. 당신은 선택할 수 있습니다

See all articles