2

Sybase 12.5.3 (ASE)を使用しています。MSSQL をかなり広範囲に使用してきましたが、Sybase は初めてです。ストアド プロシージャが非常に遅いシナリオに直面しています。比較的大きなテーブルの単一の SELECT stmt に問題を追跡しました。そのステートメントを変更すると、プロシージャーのパフォーマンスが劇的に改善されます (元に戻すと、大幅に速度が低下します。つまり、SELECT ステートメントが間違いなく原因です)。

-- Sybase optimizes and uses multi-column index... fast!<br>
SELECT ID,status,dateTime
FROM myTable
WHERE status in ('NEW','SENT')
ORDER BY ID

-- Sybase does not use index and does very slow table scan<br>
SELECT ID,status,dateTime
FROM myTable
WHERE status in (select status from allowableStatusValues)
ORDER BY ID

上記のコードは、実際のコードを改造/簡略化したものです。手順の再コンパイル、統計の更新などをすでに試みたことに注意してください。

文字列がハードコードされている場合にのみ Sybase ASE がインデックスを選択し、別のテーブルから選択するときにテーブル スキャンを選択する理由がわかりません。誰か手がかりを教えてください。よろしくお願いします。

4

6 に答える 6

2

インデックス ヒントはそれを回避しますが、おそらく解決策ではありません。

まず、allowableStatusValues.status にインデックスがあるかどうかを知りたいです。ある場合、sybase には統計があり、そこにある値の数について良い考えがあります。そうでない場合、オプティマイザーはおそらく Status がいくつの異なる値を取るかを把握できません。次に、myTable からほぼすべての行を抽出することを想定する必要があります。これを行う最善の方法は、テーブル スキャンです (カバー インデックスがない場合)。

列の統計を取得するためにインデックスを追加する必要はなくなりましたが、これがおそらく最善の方法です。

もしあなたがallowableStatusValues.statusにインデックスを持っているなら、私はあなたの統計がどれほど良いか疑問に思います. sp__optdiagのコピーを入手してください。おそらく、「ヒストグラム調整係数」と「ヒストグラム ステップ数」の値も調整する必要があります。これらをデフォルトからわずかに増やすと、オプティマイザに常に役立つより詳細な統計情報が得られます。

于 2010-03-24T13:28:20.903 に答える
2

1.ここでの問題は、コーディングの悪さです。あなたのリリースでは、貧弱なコードと貧弱なテーブル設計が主な理由 (98%) であり、オプティマイザーが誤った決定を下します (この 2 つは密接に関係しており、それぞれの割合は把握していません)。両方:

    WHERE status IN ('NEW','SENT')

    WHERE status IN (SELECT status FROM allowableStatusValues)

どちらの場合も、ASE がブラケット間の内容の作業テーブルを作成するため、標準以下です。これは簡単に回避できます (そして、結果として生じるすべての問題を回避できます)。t.status または s.status のいずれかの統計が欠落しているため (AdamH はその点に関しては正しいです)、テーブル スキャンを正しく選択します。

サブクエリにはその役割がありますが、純粋な (テーブルが関連している) 結合の代わりになることはありません。修正は次のとおりです。

    WHERE status = "NEW" OR status = "SENT"

    FROM  myTable t,
          allowableStatusValues s
    WHERE t.status = s.status

2.声明

| | 列の統計を取得するためにインデックスを追加する必要はなくなりましたが、これがおそらく最善の方法です。

間違っています。使用しないインデックスは作成しないでください。列の統計を更新したい場合は、単純に

    UPDATE STATISTICS myTable (status)

3. (a) すべての索引付けされた列および (b) すべての結合列に関する最新の統計があることを確認することが重要です。

4.はい、リリースが予定されているすべてのコード セグメントで SHOWPLAN に代わるものはありません。SET NOEXEC ONまた、実行を避けるために、次のこともできます。大きな結果セットの場合。

于 2010-10-23T09:42:45.037 に答える
1

サブクエリを結合に置き換えた場合でも、テーブルスキャンは実行されますか?

SELECT m.ID,m.status,m.dateTime 
FROM myTable m
JOIN allowableStatusValues a on m.status = a.status
ORDER BY ID 
于 2010-03-24T13:42:23.233 に答える
0

クエリの実行にかかる時間を実験的に観察するのではなく、Sybase に各クエリの実行プランを表示してもらうことを強くお勧めします。次に例を示します。

SET showplan ON
GO

-- query/procedure call goes here
SELECT id, status, datetime
FROM myTable
WHERE status IN('NEW','SENT')
ORDER BY id
GO

SET showplan OFF
GO

を使用SET showplan ONすると、Sybase は実行するステートメントごとに実行計画を生成します。これらは、クエリが適切なインデックスを使用していない場所を特定するのに非常に役立ちます。Sybase のストアド プロシージャの場合、ストアド プロシージャがコンパイルされた後に最初に実行されるときに、プロシージャ全体の実行計画が生成されます。

各クエリの計画を投稿していただければ、問題をより明確にすることができるかもしれません。

于 2010-03-23T17:05:21.710 に答える
0

驚くべきことに、インデックス ヒントを使用すると問題が解決します (以下の(index myIndexName)行を参照してください - 以下のコードを書き直して単純化したものです)。

-- using INDEX HINT
SELECT ID,status,dateTime 
FROM myTable (index myIndexName)
WHERE status in (select status from allowableStatusValues) 
ORDER BY ID 

テーブル スキャンを回避するためにこの手法を使用する必要があるのは奇妙ですが、これで終わりです。

于 2010-03-23T19:18:41.947 に答える
0

Garrett さん、簡略化されたコードだけを示すことで、問題の原因を明らかにする情報を正確に取り除いている可能性があります。

私の最初の推測は、allowableStatusValues.status と myTable.status の間の型の不一致でしょう。ただし、可能性はそれだけではありません。ninesided が述べたように、完全なクエリ プラン (showplan フラグと fmtonly フラグを使用)、および実際のテーブル定義とストアド プロシージャ ソースを使用すると、有用な回答が得られる可能性が高くなります。

于 2010-03-23T21:50:46.123 に答える