検索

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 までご連絡ください。
InnoDBバッファープールとそのパフォーマンスの重要性を説明してください。InnoDBバッファープールとそのパフォーマンスの重要性を説明してください。Apr 19, 2025 am 12:24 AM

Innodbbufferpoolは、データをキャッシュしてページをインデックス作成することにより、ディスクI/Oを削減し、データベースのパフォーマンスを改善します。その作業原則には次のものが含まれます。1。データ読み取り:Bufferpoolのデータを読む。 2。データの書き込み:データを変更した後、bufferpoolに書き込み、定期的にディスクに更新します。 3.キャッシュ管理:LRUアルゴリズムを使用して、キャッシュページを管理します。 4.読みメカニズム:隣接するデータページを事前にロードします。 BufferPoolのサイジングと複数のインスタンスを使用することにより、データベースのパフォーマンスを最適化できます。

MySQL対その他のプログラミング言語:比較MySQL対その他のプログラミング言語:比較Apr 19, 2025 am 12:22 AM

他のプログラミング言語と比較して、MySQLは主にデータの保存と管理に使用されますが、Python、Java、Cなどの他の言語は論理処理とアプリケーション開発に使用されます。 MySQLは、データ管理のニーズに適した高性能、スケーラビリティ、およびクロスプラットフォームサポートで知られていますが、他の言語は、データ分析、エンタープライズアプリケーション、システムプログラミングなどのそれぞれの分野で利点があります。

MySQLの学習:新しいユーザー向けの段階的なガイドMySQLの学習:新しいユーザー向けの段階的なガイドApr 19, 2025 am 12:19 AM

MySQLは、データストレージ、管理、分析に適した強力なオープンソースデータベース管理システムであるため、学習する価値があります。 1)MySQLは、SQLを使用してデータを操作するリレーショナルデータベースであり、構造化されたデータ管理に適しています。 2)SQL言語はMySQLと対話するための鍵であり、CRUD操作をサポートします。 3)MySQLの作業原則には、クライアント/サーバーアーキテクチャ、ストレージエンジン、クエリオプティマイザーが含まれます。 4)基本的な使用には、データベースとテーブルの作成が含まれ、高度な使用にはJoinを使用してテーブルの参加が含まれます。 5)一般的なエラーには、構文エラーと許可の問題が含まれ、デバッグスキルには、構文のチェックと説明コマンドの使用が含まれます。 6)パフォーマンスの最適化には、インデックスの使用、SQLステートメントの最適化、およびデータベースの定期的なメンテナンスが含まれます。

MySQL:初心者が習得するための必須スキルMySQL:初心者が習得するための必須スキルApr 18, 2025 am 12:24 AM

MySQLは、初心者がデータベーススキルを学ぶのに適しています。 1.MySQLサーバーとクライアントツールをインストールします。 2。selectなどの基本的なSQLクエリを理解します。 3。マスターデータ操作:テーブルを作成し、データを挿入、更新、削除します。 4.高度なスキルを学ぶ:サブクエリとウィンドウの関数。 5。デバッグと最適化:構文を確認し、インデックスを使用し、選択*を避け、制限を使用します。

MySQL:構造化データとリレーショナルデータベースMySQL:構造化データとリレーショナルデータベースApr 18, 2025 am 12:22 AM

MySQLは、テーブル構造とSQLクエリを介して構造化されたデータを効率的に管理し、外部キーを介してテーブル間関係を実装します。 1.テーブルを作成するときにデータ形式と入力を定義します。 2。外部キーを使用して、テーブル間の関係を確立します。 3。インデックス作成とクエリの最適化により、パフォーマンスを改善します。 4.データベースを定期的にバックアップおよび監視して、データのセキュリティとパフォーマンスの最適化を確保します。

MySQL:説明されている主要な機能と機能MySQL:説明されている主要な機能と機能Apr 18, 2025 am 12:17 AM

MySQLは、Web開発で広く使用されているオープンソースリレーショナルデータベース管理システムです。その重要な機能には、次のものが含まれます。1。さまざまなシナリオに適したInnodbやMyisamなどの複数のストレージエンジンをサポートします。 2。ロードバランスとデータバックアップを容易にするために、マスタースレーブレプリケーション機能を提供します。 3.クエリの最適化とインデックスの使用により、クエリ効率を改善します。

SQLの目的:MySQLデータベースとの対話SQLの目的:MySQLデータベースとの対話Apr 18, 2025 am 12:12 AM

SQLは、MySQLデータベースと対話して、データの追加、削除、変更、検査、データベース設計を実現するために使用されます。 1)SQLは、ステートメントの選択、挿入、更新、削除を介してデータ操作を実行します。 2)データベースの設計と管理に作成、変更、ドロップステートメントを使用します。 3)複雑なクエリとデータ分析は、ビジネス上の意思決定効率を改善するためにSQLを通じて実装されます。

初心者向けのMySQL:データベース管理を開始します初心者向けのMySQL:データベース管理を開始しますApr 18, 2025 am 12:10 AM

MySQLの基本操作には、データベース、テーブルの作成、およびSQLを使用してデータのCRUD操作を実行することが含まれます。 1.データベースの作成:createdatabasemy_first_db; 2。テーブルの作成:createTableBooks(idintauto_incrementprimarykey、titlevarchary(100)notnull、authorvarchar(100)notnull、published_yearint); 3.データの挿入:InsertIntoBooks(タイトル、著者、公開_year)VA

See all articles

ホット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ヘンタイを無料で生成します。

ホットツール

SublimeText3 中国語版

SublimeText3 中国語版

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

Dreamweaver Mac版

Dreamweaver Mac版

ビジュアル Web 開発ツール

AtomエディタMac版ダウンロード

AtomエディタMac版ダウンロード

最も人気のあるオープンソースエディター

SublimeText3 Mac版

SublimeText3 Mac版

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

MinGW - Minimalist GNU for Windows

MinGW - Minimalist GNU for Windows

このプロジェクトは osdn.net/projects/mingw に移行中です。引き続きそこでフォローしていただけます。 MinGW: GNU Compiler Collection (GCC) のネイティブ Windows ポートであり、ネイティブ Windows アプリケーションを構築するための自由に配布可能なインポート ライブラリとヘッダー ファイルであり、C99 機能をサポートする MSVC ランタイムの拡張機能が含まれています。すべての MinGW ソフトウェアは 64 ビット Windows プラットフォームで実行できます。