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

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

1
SARGable述語をCTEまたは派生テーブルにプッシュできるのはいつですか?
土嚢 最高品質のPosts®をブログに取り組んでいる間、私は私が実際に見つかったいくつかのオプティマイザの動作に出くわした腹立たしい興味深いです。私はすぐには説明がありませんが、少なくとも私が満足している説明はありませんので、誰かがスマートになった場合に備えてここに説明します。 追跡する場合は、2013バージョンのStack Overflowデータダンプをこちらから入手できます。コメントテーブルを使用していますが、インデックスが1つ追加されています。 CREATE INDEX [ix_ennui] ON [dbo].[Comments] ( [UserId], [Score] DESC ); クエリ1 このようにテーブルをクエリすると、奇妙なクエリプランが表示されます。 WITH x AS ( SELECT TOP 101 c.UserId, c.Text, c.Score FROM dbo.Comments AS c ORDER BY c.Score DESC ) SELECT * FROM x WHERE x.Score >= 500; ScoreのSARGable述部はCTE内にプッシュされません。計画のかなり後の時点でフィルター演算子に含まれています。 これORDER BYは、フィルターと同じ列にあるため、おかしいと思います。 クエリ2 クエリを変更すると、プッシュされます。 WITH x …

2
300,000行のテーブルで実行するのに11分かかるクエリを結合します
以下のクエリの実行には11分以上かかります。 SELECT `c`.*, `e`.`name` AS `employee_name`, `e`.`emp_no`, `d`.`code` AS `department_code`, IF(ew.code IS NOT NULL, ew.code, egw.code) AS shift_code, IF(ew.code IS NOT NULL, ew.time_in_from, egw.time_in_from) AS time_in_from, IF(ew.code IS NOT NULL, ew.time_out_to, egw.time_out_to) AS time_out_to, IF(ew.code IS NOT NULL, ew.next_day, egw.next_day) AS next_day FROM `tms_emp_badge_card` AS `c` LEFT JOIN `tms_door_record_raw` AS …

3
EXISTSクエリがインデックスシークの代わりにインデックススキャンを行うのはなぜですか?
いくつかのクエリの最適化に取り組んでいます。 以下のクエリの場合、 SET STATISTICS IO ON; DECLARE @OrderStartDate DATETIME2 = '27 feb 2016'; DECLARE @OrderEndDate DATETIME2 = '28 feb 2016'; SELECT o.strBxOrderNo , o.sintOrderStatusID , o.sintOrderChannelID , o.sintOrderTypeID , o.sdtmOrdCreated , o.sintMarketID , o.strOrderKey , o.strOfferCode , o.strCurrencyCode , o.decBCShipFullPrice , o.decBCShipFinal , o.decBCShipTax , o.decBCTotalAmount , o.decWrittenTotalAmount , o.decBCWrittenTotalAmount …

2
結合ヒントを追加すると、SQL Serverの行の見積もりが変更されるのはなぜですか?
私はいくつかのテーブルを結合し、かなり悪いパフォーマンスを発揮するクエリを持っています-行の推定はかなり(1000回)オフであり、ネストされたループ結合が選択され、複数のテーブルスキャンが発生します。クエリの形状は非常に単純で、次のようになります。 SELECT t1.id FROM t1 INNER JOIN t2 ON t1.id = t2.t1_id LEFT OUTER JOIN t3 ON t2.id = t3.t2_id LEFT OUTER JOIN t4 ON t3.t4_id = t4.id WHERE t4.id = some_GUID クエリをいじると、結合の1つにMerge結合を使用するようにヒントを出すと、実行が何倍も速くなることに気付きました。これは理解できます-結合結合は、結合されるデータにとってより良いオプションですが、SQL Serverはネストされたループを選択するだけでは正しく推定しません。 私が完全に理解していないのは、この結合ヒントがすべてのプラン演算子のすべての推定値を変更する理由です。さまざまな記事や本を読んで、計画を構築する前にカーディナリティの推定が実行されると想定したため、ヒントを使用しても推定は変更されず、SQL Serverに特定の物理結合実装を使用するよう明示的に指示します。 ただし、Mergeヒントを使用すると、すべての推定がほぼ完璧になります。なぜこれが起こるのか、ヒントなしでクエリオプティマイザーがより良い推定を行う一般的な手法はありますか?統計が明らかにこれを許可していることを考慮して? UPD:匿名化された実行計画はここにあります:https : //www.dropbox.com/s/hchfuru35qqj89s/merge_join.sqlplan ? dl = 0 https://www.dropbox.com/s/38sjtv0t7vjjfdp/no_hints_join.sqlplan?dl = 0 TF 3604、9202、9204を使用して両方のクエリで使用される統計情報を確認しましたが、これらは同じです。ただし、スキャン/シークされるインデックスはクエリによって異なります。 それに加えて、クエリを実行しようとしましたOPTION …

2
空の列値は、入力された列値と同じストレージスペースを占有しますか?
2列のテーブルがあります。両方の列のタイプはに設定されvarchar(38)ます。列の1つに空の値を持つ行を作成する場合、値が空でない場合と同じストレージスペースが必要ですか? 言い換えると、MySQLは行の作成時に列のストレージスペースを(そのタイプに応じて)予約しますか?

2
シークできない永続化計算列のインデックス
という名前のテーブルがありAddress、そのテーブルには、という永続的な計算列がありHashkeyます。列は確定的ですが、正確ではありません。シークできない一意のインデックスがあります。このクエリを実行すると、主キーが返されます。 SELECT @ADDRESSID= ISNULL(AddressId,0) FROM dbo.[Address] WHERE HashKey = @HashKey 私はこの計画を取得します: インデックスを強制すると、さらに悪い計画が得られます。 インデックスとシークの両方を強制しようとすると、エラーが発生します。 このクエリで定義されたヒントのため、クエリプロセッサはクエリプランを作成できませんでした。ヒントを指定せずに、使用せずにクエリを再送信しますSET FORCEPLAN これは、正確ではないという理由だけですか?持続するかどうかは関係ないと思いましたか? これを非計算列にすることなく、このインデックスをシーク可能にする方法はありますか? これに関する情報へのリンクはありますか? 実際のテーブル作成を投稿することはできませんが、同じ問題があるテストテーブルを次に示します。 drop TABLE [dbo].[Test] CREATE TABLE [dbo].[Test] ( [test] [VARCHAR](100) NULL, [TestGeocode] [geography] NULL, [Hashkey] AS CAST( ( hashbytes ('SHA', ( RIGHT(REPLICATE(' ', (100)) + isnull([test], ''), ( 100 )) ) + …

1
一意のインデックススキャン後に集計演算子が使用される理由
NULL不可の値に対してフィルター処理された一意のインデックスを持つテーブルがあります。クエリプランでは、distinctの使用があります。これには理由がありますか? USE tempdb CREATE TABLE T1( Id INT NOT NULL IDENTITY PRIMARY KEY ,F1 INT , F2 INT ) go CREATE UNIQUE NONCLUSTERED INDEX UK_T1 ON T1 (F1,F2) WHERE F1 IS NOT NULL AND F2 IS NOT NULL GO INSERT INTO T1(f1,F2) VALUES(1,1),(1,2),(2,1) SELECT DISTINCT F1,F2 FROM T1 WHERE F1 …

3
WHERE条件とGROUP BYを使用したSQLクエリのインデックス
WHERE条件付きのSQLクエリに使用するインデックスと、GROUP BY現在非常に遅いインデックスを決定しようとしています。 私のクエリ: SELECT group_id FROM counter WHERE ts between timestamp '2014-03-02 00:00:00.0' and timestamp '2014-03-05 12:00:00.0' GROUP BY group_id テーブルには現在32.000.000行があります。時間枠を増やすと、クエリの実行時間が非常に長くなります。 問題のテーブルは次のようになります。 CREATE TABLE counter ( id bigserial PRIMARY KEY , ts timestamp NOT NULL , group_id bigint NOT NULL ); 現在、次のインデックスがありますが、パフォーマンスはまだ遅いです。 CREATE INDEX ts_index ON counter USING btree (ts); …

3
CTE階層の最適化
以下を更新 アカウントの階層を表す一般的なアカウント/親アカウントアーキテクチャのアカウントのテーブルがあります(SQL Server 2012)。CTEを使用してVIEWを作成し、階層をハッシュしました。全体として、意図したとおりに美しく機能します。任意のレベルで階層を照会し、ブランチを簡単に確認できます。 階層の関数として返される必要があるビジネスロジックフィールドが1つあります。各アカウントレコードのフィールドは、ビジネスのサイズを記述します(CustomerCountと呼びます)。レポートする必要があるロジックは、ブランチ全体からCustomerCountをロールアップする必要があります。つまり、アカウントが与えられた場合、そのアカウントのcustomercount値と、階層に沿ったアカウントの下のすべてのブランチのすべての子を合計する必要があります。 acct4.acct3.acct2.acct1のように見えるCTE内に構築された階層フィールドを使用して、フィールドを正常に計算しました。私が直面している問題は、単純に高速化することです。この1つの計算フィールドがないと、クエリは約3秒で実行されます。計算フィールドに追加すると、4分のクエリになります。 これが正しい結果を返す、私が思いつくことができた最高のバージョンです。パフォーマンスをそれほど犠牲にすることなく、このAS A VIEWをどのように再構築できるかについてのアイデアを探しています。 私はこれが遅くなる理由を理解しています(where句で述語を計算する必要があります)が、それを構造化して同じ結果を得る別の方法を考えることはできません。 以下に、テーブルを構築し、CTEを私の環境で動作するように正確に実行するためのサンプルコードを示します。 Use Tempdb go CREATE TABLE dbo.Account ( Acctid varchar(1) NOT NULL , Name varchar(30) NULL , ParentId varchar(1) NULL , CustomerCount int NULL ); INSERT Account SELECT 'A','Best Bet',NULL,21 UNION ALL SELECT 'B','eStore','A',30 UNION ALL SELECT 'C','Big Bens','B',75 UNION …

2
実行プランを使用してT-SQLクエリを最適化する方法
過去2日間、試行錯誤と実行計画を使用して最適化しようとして費やしたSQLクエリがありますが、役に立ちません。これを行うことを許してください。しかし、私はここに実行計画全体を掲載します。簡潔にするためと会社のIPを保護するために、クエリおよび実行プランのテーブル名と列名を汎用にするように努力しました。実行計画は、SQL Sentry Plan Explorerで開くことができます。 かなりの量のT-SQLを実行しましたが、実行プランを使用してクエリを最適化することは私にとって新しい分野であり、その方法を本当に理解しようとしました。したがって、誰かがこれを手伝って、この実行計画を解読してクエリで最適化する方法を見つける方法を説明できれば、私は永遠に感謝しています。最適化するクエリはさらに多くあります。この最初のクエリを支援するための踏み台が必要です。 これはクエリです: DECLARE @Param0 DATETIME = '2013-07-29'; DECLARE @Param1 INT = CONVERT(INT, CONVERT(VARCHAR, @Param0, 112)) DECLARE @Param2 VARCHAR(50) = 'ABC'; DECLARE @Param3 VARCHAR(100) = 'DEF'; DECLARE @Param4 VARCHAR(50) = 'XYZ'; DECLARE @Param5 VARCHAR(100) = NULL; DECLARE @Param6 VARCHAR(50) = 'Text3'; SET NOCOUNT ON DECLARE @MyTableVar TABLE …

3
OFFSET…FETCHと古いスタイルのROW_NUMBERスキームとの間に実行計画の違いがあるのはなぜですか?
OFFSET ... FETCHSQL Server 2012で導入された新しいモデルは、シンプルで高速なページングを提供します。2つの形式が意味的に同一であり、非常に一般的であることを考慮すると、なぜまったく違いがあるのですか? オプティマイザーが両方を認識し、それらを(簡単に)最大限に最適化すると仮定します。 OFFSET ... FETCHこれは、コストの見積もりによると2倍速い非常に単純なケースです。 SELECT * INTO #objects FROM sys.objects SELECT * FROM ( SELECT *, ROW_NUMBER() OVER (ORDER BY object_id) r FROM #objects ) x WHERE r >= 30 AND r < (30 + 10) ORDER BY object_id SELECT * FROM #objects ORDER BY …

1
クラスター化インデックススキャンの実行回数が非常に多いのはなぜですか?
同じクエリプランを生成する2つの類似したクエリがありますが、1つのクエリプランがクラスタ化インデックススキャンを1316回実行し、もう1つのクエリプランが1回実行することを除きます。 2つのクエリの唯一の違いは、異なる日付基準です。長時間実行されるクエリは、実際には日付基準を絞り込み、引き戻すデータを減らします。 両方のクエリに役立ついくつかのインデックスを特定しましたが、クラスター化インデックススキャン演算子が1回実行するクエリと実質的に同じクエリで1316回実行する理由を理解したいだけです。 スキャンされているPKの統計を確認しましたが、比較的最新です。 元のクエリ: select distinct FIR_Incident.IncidentID from FIR_Incident left join ( select incident_id as exported_incident_id from postnfirssummary ) exported_incidents on exported_incidents.exported_incident_id = fir_incident.incidentid where FI_IncidentDate between '2011-06-01 00:00:00.000' and '2011-07-01 00:00:00.000' and exported_incidents.exported_incident_id is not null この計画を生成します。 日付範囲の基準を絞り込んだ後: select distinct FIR_Incident.IncidentID from FIR_Incident left join ( select incident_id …

2
最適化:プロシージャの最上部への変数宣言の移動
いくつかのストアドプロシージャの最適化に取り組んでいる間、DBAに座って、高いブロッキングおよび/または高い読み取り/書き込みアクティビティでいくつかのストアドプロシージャを実行しました。 DBAが言及したことの1つTABLEは、再コンパイルを回避するために、ストアドプロシージャの最上部ですべての変数(特に変数)を宣言する必要があることです。 これは私がこれを聞いた最初のものであり、私たちが持っているすべての異なるストアドプロシージャを再検討する前に、いくつかの確認を探していました。彼はそれを「コードの遅い表示」と呼び、再コンパイルはブロッキングを説明するスキーマをロックしていました。 すべての変数宣言をストアドプロシージャの先頭に移動すると、再コンパイルが減りますか?

2
「tmpテーブルへのコピー」が非常に遅い
これはクエリの私の例です: SELECT nickname, CASE class_id WHEN 1 THEN 'Druid' WHEN 2 THEN 'Necromancer' WHEN 3 THEN 'Mage' WHEN 4 THEN 'Priest' WHEN 5 THEN 'Warrior' WHEN 6 THEN 'Stalker' WHEN 7 THEN 'Paladin' WHEN 8 THEN 'Psionic' END class_name, ROUND(AVG(level),2) level, ROUND(AVG(tabard_id),2) tabard, CASE rank_id WHEN 1 THEN 'Leader' WHEN …

1
インデックスは `= any()`では使用されず、 `in`で使用されます
テーブルにtは2つのインデックスがあります。 create table t (a int, b int); create type int_pair as (a int, b int); create index t_row_idx on t (((a,b)::int_pair)); create index t_a_b_idx on t (a,b); insert into t (a,b) select i, i from generate_series(1, 100000) g(i) ; any演算子ではインデックスは使用されません。 explain analyze select * from t where (a,b) = …

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