タグ付けされた質問 「optimization」

データベースのコンテキストでは、最適化とは、クエリオプティマイザが効率的な物理実行プランを選択するプロセスを指します。

1
CTEがインラインサブクエリよりもはるかに悪いのはなぜですか
クエリプランナーがpostgresqlでどのように機能するかをよりよく理解しようとしています。 私はこのクエリを持っています: select id from users where id <> 2 and gender = (select gender from users where id = 2) order by latest_location::geometry <-> (select latest_location from users where id = 2) ASC limit 50 私のデータベースでは10ms未満で実行され、usersテーブルには約500kのエントリがあります。 次に、副選択の重複を避けるために、次のようにクエリをCTEとして書き直すことができると考えました。 with me as ( select * from users where id = 2 …

1
SQL ServerがCTEを「最適化フェンス」として使用する場合に決定するルールは何ですか?
しばらく前に、Brent OzarがSQL ServerとPostgreSQLの違いのいくつかを詳しく説明した投稿を公開しました: SQL ServerとPostgreSQLの2つの重要な違い 最初のポイント(「CTEは最適化フェンス」)が私の目を引きました。提供されている例では、SQL ServerがCTEとメインクエリを組み合わせ、それを単一のクエリとして最適化している( PostgreSQL)。 ただし、この動作は、SQL ServerがCTEを最適化フェンスとして扱う他のブログやトレーニングクラスで見た例とは逆のようです。これにより、インデックスの使用やパフォーマンスの向上などが可能になります。次に例を示します。 星を選択するより良い方法 したがって、SQL ServerはCTEを最適化のフェンスとして「称賛」しているようです。SQL ServerがCTEを最適化フェンスとして確実に尊重する既知のケース(またはその逆の動作)の特定のリストを文書化する優れたリソースはありますか?

2
なぜこれがより速く、安全に使用できますか?(最初の文字がアルファベットの場合)
要するに、非常に大きな人々のテーブルからの値で人々の小さなテーブルを更新しています。最近のテストでは、この更新の実行に約5分かかります。 私たちは可能な限り最も賢い最適化のように思われるものに偶然出会いました。同じクエリが2分未満で実行され、同じ結果が完全に生成されます。 これがクエリです。最後の行は「最適化」として追加されます。クエリ時間が大幅に減少するのはなぜですか?何かが足りませんか?これは将来的に問題を引き起こす可能性がありますか? UPDATE smallTbl SET smallTbl.importantValue = largeTbl.importantValue FROM smallTableOfPeople smallTbl JOIN largeTableOfPeople largeTbl ON largeTbl.birth_date = smallTbl.birthDate AND DIFFERENCE(TRIM(smallTbl.last_name),TRIM(largeTbl.last_name)) = 4 AND DIFFERENCE(TRIM(smallTbl.first_name),TRIM(largeTbl.first_name)) = 4 WHERE smallTbl.importantValue IS NULL -- The following line is "the optimization" AND LEFT(TRIM(largeTbl.last_name), 1) IN ('a','à','á','b','c','d','e','è','é','f','g','h','i','j','k','l','m','n','o','ô','ö','p','q','r','s','t','u','ü','v','w','x','y','z','æ','ä','ø','å') テクニカルノート:テストする文字のリストには、さらに数文字が必要になる場合があることを認識しています。また、「DIFFERENCE」を使用した場合のエラーの明らかなマージンも認識しています。 クエリプラン(通常): https : //www.brentozar.com/pastetheplan/?id=rypV84y7V クエリプラン( "最適化"付き): …


1
クラスタ化インデックスを使用してSQL Serverテーブルからデータを削除するときに、Bツリーは再調整されますか?
SQL Serverデータベースに、主キーにクラスター化インデックスを持つテーブルがあります。テーブルには100万行あります。テーブルから10K行を削除した場合、削除操作の実行中にインデックスが再構築されますか? 削除操作はストアドプロシージャの一部です。一度に複数のクライアントがストアドプロシージャを実行できますが、個々の実行ごとに独自の行のセット(主キーによって一意に識別される)が削除されます。複数のクライアントがプロシージャを実行すると、キーロック(タイプU)がブロックされます。ブロッカーロックは同じテーブルの行に属しており、同時に実行されているトランザクションの一部ではありません。各実行はそれ自体の行のセットを削除しようとしているため、ブロックはありません。ロックのエスカレーションはオフになっているため、発生していません。 削除操作によってインデックスが再調整されるため、再構築プロセス中にテーブルの任意の行でキーロックが発生する可能性があると思います。 これについてのご意見をいただければ幸いです。

2
インデックスを追加することのコスト/メリットを判断するにはどうすればよいですか?
クレイグ・リンガーによると: 通常、参照側の外部キー列(またはそれを含む)にインデックスを作成することをお勧めしますが、必須ではありません。追加するインデックスごとにDML操作が少し遅くなるためINSERT、UPDATEまたはごとにパフォーマンスコストが発生しDELETEます。インデックスがめったに使用されない場合、その価値はないかもしれません。 インデックスを追加するメリットがコストを上回るかどうかをどのように判断しますか? インデックスを追加する前後に単体テストのプロファイルを作成し、全体的なパフォーマンスの向上を確認しますか?それとももっと良い方法がありますか?

1
再帰CTEのカーディナリティを「ヒント」にするにはどうすればよいですか?
最小限の例として次の再帰CTEを使用していますが、一般的に、オプティマイザは再帰CTEにデフォルトの「推測」カーディナリティを使用する必要があります。 with recursive w(n) as ( select 1 union all select n+1 from w where n<5 ) select * from w; /* n --- 1 2 3 4 5 */ explain analyze with recursive w(n) as ( select 1 union all select n+1 from w where n<5 ) select * …

1
式の型変換は、クエリプランの選択で「CardinalityEstimate」に影響を与える可能性がありますか?
パーティションビューに履歴データを格納するアーカイブデータベースを維持しています。パーティション化列は日時です。ビューの下の各テーブルには、1か月分のデータが格納されます。 各テーブルのイベントを、datetime列のチェック制約で制約します。これにより、オプティマイザは、イベント日時列でフィルタするクエリを検索するテーブルを制限できます。 チェック制約の名前はSQL Serverによって生成されているため、名前を確認しても何を行うかを知るのは困難です。 制約名を「CK_TableName_Partition」の形式にしたい。 このクエリを使用し、sql_text列からデータをコピーして、名前変更スクリプトを生成できます。WHERE句は、SQL Serverによって生成されたように見える名前のチェック制約に一致します。 SELECT checks.name AS check_name, tabs.name AS table_name, skemas.name AS schema_name, cols.name AS column_name, N' EXECUTE sys.sp_rename @objname = N''' + skemas.name + N'.' + checks.name + N''', @newname = N''CK_' + tabs.name + N'_Partition'', @objtype = ''OBJECT'';' AS sql_text FROM sys.check_constraints AS checks …

3
一般に、データベースの行のすべての変更の記録はどのように保存されますか?
私が取り組んでいるプロジェクトでは、さらに監査またはロールバックするために、データベースの一部のテーブルの行に対するすべての変更を追跡する必要があります。その行を誰がどのIPアドレスからいつ変更したかを簡単に見つけ、以前のバージョンを復元できる必要があります。 同様のものが、たとえばStack Exchangeでも使用されています。他の人の質問を変更すると、自分が変更したことがわかり、変更をロールバックできます。 現在のスキーマが平均的なビジネスアプリとほとんど同じプロパティ(以下)を持っている場合、オブジェクトのすべての変更をデータベースに格納するために使用される一般的な手法は何ですか? オブジェクトのサイズは比較的小さいです。nvarchar(1000)たとえば、バイナリデータの巨大なblobはなくても、ディスクに直接保存され、Microsoft SQL ではなく直接アクセスされる場合がありますfilestream。 データベースの負荷はかなり低く、データベース全体はサーバー上の1つの仮想マシンによって処理されます。 以前のバージョンへのアクセスは、最新バージョンへのアクセスほど高速である必要はありませんが、それでも最新の状態¹であり、遅すぎない必要があります²。 <tl-dr> 次のようなケースを考えましたが、そういうシナリオはあまり経験がないので、他の人の意見を聞いてみました。 IDとバージョンで行を区別して、すべてを同じテーブルに格納します。IMO、それは深刻な愚かであり、パフォーマンスレベルで遅かれ早かれ傷つけるでしょう。このアプローチでは、最新のアイテムとバージョントレースに異なるセキュリティレベルを設定することも不可能です。最後に、すべてのクエリを記述するのはより複雑になります。実際、最新のデータにアクセスするには、IDですべてをグループ化し、各グループで最後のバージョンを取得する必要があります。 1つのテーブルに最新バージョンを保存し、変更のたびに、古いバージョンを別のスキーマの別のテーブルにコピーします。欠点は、変更されていなくても、常にすべての値を保存することです。変更された値をに設定することnullは解決策ではありません。値がに、nullまたはに変更されたときにも追跡する必要があるためnullです。 最新バージョンを1つのテーブルに保存し、変更されたプロパティのリストと以前の値を別のテーブルに保存します。これは、二つの傷のようだ:最も重要なのは同じ列に以前の値の異質なタイプをソートする唯一の方法は持っているということですbinary(max)。2つ目は、以前のバージョンをユーザーに表示するときに、このような構造を使用するのがより困難になると私は考えています。 前の2つのポイントと同じことを行いますが、バージョンを別のデータベースに保存します。パフォーマンスに関しては、同じデータベースに以前のバージョンを置くことで最新バージョンへのアクセスが遅くなるのを避けるために興味深いかもしれません。それでも、これは時期尚早の最適化であり、同じデータベースに古いバージョンと最新のバージョンを置くことがボトルネックであるという証拠がある場合にのみ実行する必要があると思います。 </ tl-dr> ¹たとえば、HTTPログの場合と同様に、ログファイルに変更を保存し、サーバーの負荷が最も低い夜間にログからデータベースにデータをフラッシュすることはできません。異なるバージョンに関する情報は、すぐに、またはほぼすぐに入手できる必要があります。数秒の遅延は許容範囲です。 ²情報へのアクセスはそれほど頻繁ではなく、特定のユーザーグループのみがアクセスしますが、バージョンのリストが表示されるまで30秒間待つように強制することはできません。この場合も、数秒の遅延は許容されます。

2
PostgreSQLはNULL以外のDEFAULTを含む列の追加を最適化しますか?
値をNOT NULL持つ列を追加するDEFAULT場合-PostgreSQLはこの操作を最適化しますか? テーブルにn行がある場合、最適化されていないalter-table-add-columnは、デフォルト値のn回の書き込みを生成します。最適化により、DBは即座に新しい列を作成し、適切なインデックスデータ構造でその列の非デフォルト値が見つからない場合に返されるデフォルト値のコピーを1つだけ保存します。 たとえば、Oracle 11gにはそのような最適化があります。

3
主キーの自己結合
N自己結合で構成されるこのクエリについて考えてみます。 select t1.* from [Table] as t1 join [Table] as t2 on t1.Id = t2.Id -- ... join [Table] as tN on t1.Id = tN.Id N個のクラスター化インデックススキャンとN-1個のマージ結合を含む実行プランを作成します。 正直なところ、すべての結合を最適化せずに1つのクラスター化インデックススキャンだけを行う理由はありません。つまり、元のクエリを次のように最適化します。 select t1.* from [Table] as t1 ご質問 結合が最適化されないのはなぜですか? すべての結合が結果セットを変更しないと言うのは数学的に正しくありませんか? テスト済み: ソースサーバーのバージョン:SQL Server 2014(12.0.4213) ソースデータベースエンジンエディション:Microsoft SQL Server Standard Edition ソースデータベースエンジンの種類:スタンドアロンSQLサーバー 互換性レベル:SQL Server 2008(100) クエリは意味がありません。それはちょうど私の頭に浮かんできました、そして私はそれについて今興味があります。 …

1
永続的な計算された列が原因でスキャン
通常の列を永続的な計算列に変換すると、このクエリでインデックスシークを実行できなくなります。どうして? 2016 SP1 CU1を含むいくつかのSQL Serverバージョンでテストされています。 レプロス 計算された列 通常の列 問題はtable1、col7です。 テーブルとクエリは、オリジナルの部分的な(そして簡略化された)バージョンです。クエリが別の方法で書き直される可能性があることは承知しており、何らかの理由で問題を回避しますが、コードに触れないようにする必要がありtable1ます。 ポールホワイトが示したように(ありがとう!)、シークは強制された場合に利用可能になるため、オプティマイザによってシークが選択されない理由と、シークを変更することなく、必要に応じてシークを実行するために別の方法を実行できるかどうかが問題になります。コード? 問題のある部分を明確にするために、不良な実行計画の関連するスキャンを以下に示します。

3
実行プランはINDEXを使用せず、テーブルスキャンを使用します
インデックスまたはテーブルスキャンを使用する場合、SQL Serverは統計を使用してどちらが優れているかを確認します。 2,000万行のテーブルがあります。(SnapshotKey、Measure)のインデックスと次のクエリがあります。 select Measure, SnapshotKey, MeasureBand from t1 where Measure = 'FinanceFICOScore' group by Measure, SnapshotKey, MeasureBand クエリは500k行を返します。したがって、クエリはテーブルの行の2.5%のみを選択します。 問題は、SQL Serverが私が持っている非クラスター化インデックスを使用せず、代わりにテーブルスキャンを使用する理由です。 統計を更新しました。 ただし、クエリのパフォーマンスは良好です。 テーブルスキャン 強制インデックス テーブル/インデックス構造 CREATE TABLE [t1]( [SnapshotKey] [int] NOT NULL, [SnapshotDt] [date] NOT NULL, [Measure] [nvarchar](30) NOT NULL, [MeasureBand] [nvarchar](30) NOT NULL, -- and many more fields …

5
シークを期待しながらスキャンを取得
SELECTステートメントを最適化する必要がありますが、SQL Serverはシークではなく常にインデックススキャンを実行します。これはもちろん、ストアドプロシージャ内にあるクエリです。 CREATE PROCEDURE dbo.something @Status INT = NULL, @IsUserGotAnActiveDirectoryUser BIT = NULL AS SELECT [IdNumber], [Code], [Status], [Sex], [FirstName], [LastName], [Profession], [BirthDate], [HireDate], [ActiveDirectoryUser] FROM Employee WHERE (@Status IS NULL OR [Status] = @Status) AND ( @IsUserGotAnActiveDirectoryUser IS NULL OR ( @IsUserGotAnActiveDirectoryUser IS NOT NULL AND ( @IsUserGotAnActiveDirectoryUser = …

1
PAGELATCH_ *待機タイプで待機しているブロックされたセッション?
編集:セッションレポートがブロックされているがPAGELATCH_*、LCK_M_関連する待機タイプではなく、で待機しているのはなぜですか? 以前は、SQLサーバーはブロッキングセッションのみをblocking_session_Id列で報告すると想定していました。ブロックされたセッションが論理ロックを待機していて、などのほかのものがなかった場合PAGELATCH_*。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.