SQL查询优化

Jun 07, 2016 pm 05:43 PM
最適化 お問い合わせ

SQL查询优化 很多人不知道SQL语句在SQL SERVER中是如何执行的,他们担心自己所写的SQL语句会被SQL SERVER误解。比如: select * from table1 where and tID 10000 和执行: select * from table1 where tID 10000 and 一些人不知道以上两条语句的执行效率是否

SQL查询优化

很多人不知道SQL语句在SQL SERVER中是如何执行的,他们担心自己所写的SQL语句会被SQL SERVER误解。比如:  

select * from table1 where and tID > 10000  

和执行:  

select * from table1 where tID > 10000 and  

一些人不知道以上两条语句的执行效率是否一样,因为如果简单的从语句先后上看,这两个语句的确是不一样,如果tID是一个聚合索引,那么后一句仅仅从表的10000条以后的记录中查找就行了;而前一句则要先从全表中查找看有几个name='zhangsan'的,而后再根据限制条件条件tID>10000来提出查询结果。  

事实上,这样的担心是不必要的。SQL SERVER中有一个“查询分析优化器”,它可以计算出where子句中的搜索条件并确定哪个索引能缩小表扫描的搜索空间,也就是说,它能实现自动优化。  

虽然查询优化器可以根据where子句自动的进行查询优化,但大家仍然有必要了解一下“查询优化器”的工作原理,如非这样,有时查询优化器就会不按照您的本意进行快速查询。  

在查询分析阶段,查询优化器查看查询的每个阶段并决定限制需要扫描的数据量是否有用。如果一个阶段可以被用作一个扫描参数(SARG),那么就称之为可优化的,并且可以利用索引快速获得所需数据。  

SARG的定义:用于限制搜索的一个操作,因为它通常是指一个特定的匹配,一个值得范围内的匹配或者两个以上条件的AND连接。形式如下:  

列名 操作符   

或  

操作符列名  

列名可以出现在操作符的一边,而常数或变量出现在操作符的另一边。如:  

Name=’张三’  

价格>5000  

5000

Name=’张三’ and 价格>5000  

如果一个表达式不能满足SARG的形式,那它就无法限制搜索的范围了,也就是SQL SERVER必须对每一行都判断它是否满足WHERE子句中的所有条件。所以一个索引对于不满足SARG形式的表达式来说是无用的。  

介绍完SARG后,我们来总结一下使用SARG以及在实践中遇到的和某些资料上结论不同的经验:  

1、Like语句是否属于SARG取决于所使用的通配符的类型 

如:name like ‘张%’ ,这就属于SARG  

而:name like ‘%张’ ,就不属于SARG。  

原因是通配符%在字符串的开通使得索引无法使用。  

2、or 会引起全表扫描 

Name=’张三’ and 价格>5000 符号SARG,而:Name=’张三’ or 价格>5000 则不符合SARG。使用or会引起全表扫描。  

3、非操作符、函数引起的不满足SARG形式的语句 

不满足SARG形式的语句最典型的情况就是包括非操作符的语句,如:NOT、!=、、!、NOT EXISTS、NOT IN、NOT LIKE等,另外还有函数。下面就是几个不满足SARG形式的例子:  

ABS(价格)

Name like ‘%三’  

有些表达式,如:  

WHERE 价格*2>5000  

SQL SERVER也会认为是SARG,SQL SERVER会将此式转化为:  

WHERE 价格>2500/2  

但我们不推荐这样使用,因为有时SQL SERVER不能保证这种转化与原始表达式是完全等价的。  

4、IN 的作用相当与OR 

语句:  

Select * from table1 where tid in (2,3)  

和  

Select * from table1 where tid=2 or tid=3  

是一样的,都会引起全表扫描,如果tid上有索引,其索引也会失效。  

5、尽量少用NOT 

6、exists 和 in 的执行效率是一样的 

很多资料上都显示说,exists要比in的执行效率要高,同时应尽可能的用not exists来代替not in。但事实上,我试验了一下,发现二者无论是前面带不带not,香港虚拟主机,二者之间的执行效率都是一样的。因为涉及子查询,我们试验这次用SQL SERVER自带的pubs数据库。运行前我们可以把SQL SERVER的statistics I/O状态打开。  

(1)select title,price from titles where title_id in (select title_id from sales where qty>30)  

该句的执行结果为:  

表 'sales'。扫描计数 18,逻辑读 56 次,物理读 0 次,预读 0 次。  

表 'titles'。扫描计数 1,逻辑读 2 次,物理读 0 次,预读 0 次。  

(2)select title,price from titles where exists (select * from sales where sales.title_id=titles.title_id and qty>30)  

第二句的执行结果为:  

表 'sales'。扫描计数 18,逻辑读 56 次,物理读 0 次,预读 0 次。  

表 'titles'。扫描计数 1,逻辑读 2 次,物理读 0 次,预读 0 次。  

我们从此可以看到用exists和用in的执行效率是一样的。  

7、用函数charindex()和前面加通配符%的LIKE执行效率一样 

前面,我们谈到,如果在LIKE前面加上通配符%,那么将会引起全表扫描,美国服务器,所以其执行效率是低下的。但有的资料介绍说,用函数charindex()来代替LIKE速度会有大的提升,经我试验,发现这种说明也是错误的:  

select gid,title,fariqi,reader from tgongwen where charindex('刑侦支队',reader)>0 and fariqi>'2004-5-5'  

用时:7秒,另外:扫描计数 4,逻辑读 7155 次,物理读 0 次,预读 0 次。  

select gid,title,fariqi,reader from tgongwen where reader like '%' + '刑侦支队' + '%' and fariqi>'2004-5-5'  

用时:7秒,另外:扫描计数 4,逻辑读 7155 次,物理读 0 次,预读 0 次。  

8、union并不绝对比or的执行效率高 

我们前面已经谈到了在where子句中使用or会引起全表扫描,一般的,我所见过的资料都是推荐这里用union来代替or。事实证明,这种说法对于大部分都是适用的。  

select gid,fariqi,neibuyonghu,reader,title from Tgongwen where fariqi='2004-9-16' or gid>9990000  

用时:68秒。扫描计数 1,逻辑读 404008 次,物理读 283 次,预读 392163 次。  

select gid,fariqi,neibuyonghu,reader,title from Tgongwen where fariqi='2004-9-16'  

union  

select gid,fariqi,neibuyonghu,reader,title from Tgongwen where gid>9990000  

用时:9秒。扫描计数 8,逻辑读 67489 次,物理读 216 次,预读 7499 次。  

看来,用union在通常情况下比用or的效率要高的多。  

但经过试验,笔者发现如果or两边的查询列是一样的话,那么用union则反倒和用or的执行速度差很多,虽然这里union扫描的是索引,而or扫描的是全表。  

select gid,fariqi,neibuyonghu,reader,title from Tgongwen where fariqi='2004-9-16' or fariqi='2004-2-5'  

用时:6423毫秒。扫描计数 2,逻辑读 14726 次,物理读 1 次,预读 7176 次。  

select gid,fariqi,neibuyonghu,reader,title from Tgongwen where fariqi='2004-9-16'  

union  

select gid,fariqi,neibuyonghu,reader,title from Tgongwen where fariqi='2004-2-5'  

用时:11640毫秒。扫描计数 8,逻辑读 14806 次,物理读 108 次,预读 1144 次。  

9、字段提取要按照“需多少、提多少”的原则,避免“select *” 

我们来做一个试验:  

select top 10000 gid,fariqi,reader,title from tgongwen order by gid desc  

用时:4673毫秒  

select top 10000 gid,fariqi,title from tgongwen order by gid desc  

用时:1376毫秒  

select top 10000 gid,fariqi from tgongwen order by gid desc  

用时:80毫秒  

由此看来,我们每少提取一个字段,数据的提取速度就会有相应的提升。提升的速度还要看您舍弃的字段的大小来判断。  

10、count(*)不比count(字段)慢 

某些资料上说:用*会统计所有列,显然要比一个世界的列名效率低。这种说法其实是没有根据的。我们来看:  

select count(*) from Tgongwen  

用时:1500毫秒  

select count(gid) from Tgongwen  

用时:1483毫秒  

select count(fariqi) from Tgongwen  

用时:3140毫秒  

select count(title) from Tgongwen  

用时:52050毫秒  

从以上可以看出,如果用count(*)和用count(主键)的速度是相当的,而count(*)却比其他任何除主键以外的字段汇总速度要快,而且字段越长,汇总的速度就越慢。我想,如果用count(*), SQL SERVER可能会自动查找最小字段来汇总的。当然,如果您直接写count(主键)将会来的更直接些。  

11、order by按聚集索引列排序效率最高 

我们来看:(gid是主键,fariqi是聚合索引列)  

select top 10000 gid,fariqi,reader,title from tgongwen  

用时:196 毫秒。 扫描计数 1,逻辑读 289 次,物理读 1 次,预读 1527 次。  

select top 10000 gid,fariqi,reader,title from tgongwen order by gid asc  

用时:4720毫秒。 扫描计数 1,逻辑读 41956 次,物理读 0 次,预读 1287 次。  

select top 10000 gid,fariqi,reader,title from tgongwen order by gid desc  

用时:4736毫秒。 扫描计数 1,逻辑读 55350 次,物理读 10 次,预读 775 次。  

select top 10000 gid,fariqi,reader,title from tgongwen order by fariqi asc  

用时:173毫秒。 扫描计数 1,逻辑读 290 次,物理读 0 次,预读 0 次。  

select top 10000 gid,fariqi,reader,title from tgongwen order by fariqi desc  

用时:156毫秒。 扫描计数 1,逻辑读 289 次,物理读 0 次,虚拟主机,预读 0 次。  

从以上我们可以看出,不排序的速度以及逻辑读次数都是和“order by 聚集索引列” 的速度是相当的,但这些都比“order by 非聚集索引列”的查询速度是快得多的。  

同时,按照某个字段进行排序的时候,无论是正序还是倒序,速度是基本相当的。  

12、高效的TOP 

事实上,在查询和提取超大容量的数据集时,影响数据库响应时间的最大因素不是数据查找,而是物理的I/0操作。如:  

select top 10 * from (  

select top 10000 gid,fariqi,title from tgongwen  

where neibuyonghu='办公室'  

order by gid desc) as a  

order by gid asc  

这条语句,从理论上讲,整条语句的执行时间应该比子句的执行时间长,但事实相反。因为,子句执行后返回的是10000条记录,而整条语句仅返回10条语句,所以影响数据库响应时间最大的因素是物理I/O操作。而限制物理I/O操作此处的最有效方法之一就是使用TOP关键词了。TOP关键词是SQL SERVER中经过系统优化过的一个用来提取前几条或前几个百分比数据的词。经笔者在实践中的应用,发现TOP确实很好用,效率也很高。但这个词在另外一个大型数据库ORACLE中却没有,这不能说不是一个遗憾,虽然在ORACLE中可以用其他方法(如:rownumber)来解决。在以后的关于“实现千万级数据的分页显示存储过程”的讨论中,我们就将用到TOP这个关键词。  

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、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ヘンタイを無料で生成します。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

12306 過去のチケット購入記録の確認方法 過去のチケット購入記録の確認方法 12306 過去のチケット購入記録の確認方法 過去のチケット購入記録の確認方法 Mar 28, 2024 pm 03:11 PM

12306 チケット予約アプリの最新バージョンをダウンロードします。誰もが非常に満足している旅行チケット購入ソフトウェアです。行きたい場所に行くのに非常に便利です。ソフトウェアには多くのチケット ソースが提供されています。本物のチケットを渡すだけで済みます。 - 氏名認証によるオンラインチケット購入 全ユーザー 旅行券や航空券を簡単に購入でき、さまざまな割引が受けられます。また、チケットを入手するための事前予約も開始できます。ホテルや特別な車の送迎も予約できます。これを使用すると、ワンクリックで行きたい場所に行き、チケットを購入できます。旅行がより簡単で便利になり、すべての人に旅行体験を提供します編集者はオンラインで詳細を説明するようになり、12306 人のユーザーに過去のチケット購入記録を表示する方法が提供されます。 1. Railway 12306 を開き、右下隅の [My] をクリックして、[My Order] をクリックします。 2. 注文ページで [Paid] をクリックします。 3. 有料ページにて

Xuexin.com で学歴を確認する方法 Xuexin.com で学歴を確認する方法 Mar 28, 2024 pm 04:31 PM

Xuexin.com で私の学歴を確認するにはどうすればよいですか? Xuexin.com で学歴を確認できますが、多くのユーザーは Xuexin.com で学歴を確認する方法を知りません。次に、エディターが Xuexin.com で学歴を確認する方法に関するグラフィック チュートリアルを提供します。興味のあるユーザーはぜひ見に来てください! Xuexin.com の使用方法チュートリアル: Xuexin.com で学歴を確認する方法 1. Xuexin.com の入り口: https://www.chsi.com.cn/ 2. Web サイトのクエリ: ステップ 1: Xuexin.com のアドレスをクリックします。上記をクリックしてホームページに入ります [教育クエリ]をクリックします; ステップ2: 最新のWebページで下図の矢印に示すように[クエリ]をクリックします; ステップ3: 新しいページで[学術単位ファイルにログイン]をクリックします; ステップ4: ログインページで情報を入力し、[ログイン]をクリックします。

MySQL と PL/SQL の類似点と相違点の比較 MySQL と PL/SQL の類似点と相違点の比較 Mar 16, 2024 am 11:15 AM

MySQL と PL/SQL は 2 つの異なるデータベース管理システムであり、それぞれリレーショナル データベースと手続き型言語の特性を表しています。この記事では、具体的なコード例を示しながら、MySQL と PL/SQL の類似点と相違点を比較します。 MySQL は、構造化照会言語 (SQL) を使用してデータベースを管理および操作する、一般的なリレーショナル データベース管理システムです。 PL/SQL は Oracle データベースに固有の手続き型言語であり、ストアド プロシージャ、トリガー、関数などのデータベース オブジェクトを記述するために使用されます。同じ

C++ プログラムの最適化: 時間の複雑さを軽減する手法 C++ プログラムの最適化: 時間の複雑さを軽減する手法 Jun 01, 2024 am 11:19 AM

時間計算量は、入力のサイズに対するアルゴリズムの実行時間を測定します。 C++ プログラムの時間の複雑さを軽減するためのヒントには、適切なコンテナー (ベクター、リストなど) を選択して、データのストレージと管理を最適化することが含まれます。クイックソートなどの効率的なアルゴリズムを利用して計算時間を短縮します。複数の操作を排除して二重カウントを削減します。条件分岐を使用して、不必要な計算を回避します。二分探索などのより高速なアルゴリズムを使用して線形探索を最適化します。

WIN7システムのスタートアップ項目を最適化する方法 WIN7システムのスタートアップ項目を最適化する方法 Mar 26, 2024 pm 06:20 PM

1. デスクトップでキーの組み合わせ (win キー + R) を押してファイル名を指定して実行ウィンドウを開き、[regedit] と入力して Enter キーを押して確定します。 2. レジストリ エディターを開いた後、[HKEY_CURRENT_USERSoftwareMicrosoftWindowsCurrentVersionExplorer] をクリックして展開し、ディレクトリに Serialize 項目があるかどうかを確認します。ない場合は、エクスプローラーを右クリックして新しい項目を作成し、Serialize という名前を付けます。 3. 次に、「シリアル化」をクリックし、右側のペインの空白スペースを右クリックして、新しい DWORD (32) ビット値を作成し、「Star」という名前を付けます。

Vivox100s のパラメーター構成が明らかに: プロセッサーのパフォーマンスを最適化するには? Vivox100s のパラメーター構成が明らかに: プロセッサーのパフォーマンスを最適化するには? Mar 24, 2024 am 10:27 AM

Vivox100s のパラメーター構成が明らかに: プロセッサーのパフォーマンスを最適化するには?テクノロジーが急速に発展する今日、スマートフォンは私たちの日常生活に欠かせないものとなっています。スマートフォンの重要な部分であるプロセッサのパフォーマンスの最適化は、携帯電話のユーザー エクスペリエンスに直接関係します。注目度の高いスマートフォンとして、Vivox100s のパラメータ構成は多くの注目を集めており、特にプロセッサー性能の最適化はユーザーからの注目を集めています。プロセッサは携帯電話の「頭脳」として、携帯電話の動作速度に直接影響します。

PHP 関数の非効率性を解決するにはどのような方法がありますか? PHP 関数の非効率性を解決するにはどのような方法がありますか? May 02, 2024 pm 01:48 PM

PHP 関数の効率を最適化する 5 つの方法: 変数の不必要なコピーを避ける。参照を使用して変数のコピーを回避します。繰り返しの関数呼び出しを避けてください。単純な関数をインライン化します。配列を使用したループの最適化。

「黒神話:悟空」Xbox版は「メモリリーク」により遅延、PS5版は最適化中 「黒神話:悟空」Xbox版は「メモリリーク」により遅延、PS5版は最適化中 Aug 27, 2024 pm 03:38 PM

最近、「Black Myth: Wukong」は世界中で大きな注目を集めており、各プラットフォームでの同時オンライン人口は過去最高に達しており、このゲームは複数のプラットフォームで大きな商業的成功を収めています。 『Black Myth: Wukong』のXbox版は延期 『Black Myth: Wukong』はPCとPS5プラットフォームでリリースされているが、Xbox版については明確な情報はない。 『Black Myth: Wukong』がXboxプラットフォームで発売されることを関係者が認めたことが分かりました。ただし、具体的な発売日はまだ発表されていない。 Xbox 版の遅延は技術的な問題によるものであると最近報告されました。関連ブロガーによると、同氏はGamescom期間中の開発者や「Xbox関係者」とのやり取りから、Xbox版「Black Myth: Wukong」が存在することを知ったという。

See all articles