2009-04-22 13 views
1

私は、私が取り組んでいるアプリケーションで約90のクエリから同じ3行のサブクエリを排除するために "ビュー"を作成したいと思います。ストアドプロシージャを「動的」ビューとして使用するか?

問題は、サブクエリに変数に基づく条件が含まれていることです。

SELECT * FROM items WHERE id NOT IN (
    SELECT item_id FROM excluded_items WHERE user_id = 123 
); 

可変でない場合、私は単純にビューを作成して終了できます。

私はこの場合に何をすべきかわかりません。それはこのような何かを呼び出すことができるように、私は目的のレコードセットを返すストアドプロシージャを作成するように誘惑していますビューの背後に同じ考え方を採用:

SELECT * FROM user_items(123); 

今、私はこのアイテムを更新するための単一の場所を持っています除外およびその他の条件がありますが、そのSPの結果を他のテーブルと結合したい場合、どのようにインデックスが影響を受けるかはわかりません。

だから、この良い/悪い練習ですか?それを行う別の方法がありますか、それを吸い込み、このサブクエリを複製し続ける必要がありますか?

答えて

3

いつものようにあなたの走行距離はです。これがあなたのコード構文に関して良い習慣であることを心配しているなら、私はそれが重要だとは思わない。レコードセットを返すためにストアドプロシージャを使用するのはかなり普通のことですが、それが開発時間を節約すれば、それはなぜですか?しかし、クエリの実行時間に対するコストが、プログラマとしての生産性を上回るビジネスコストを負担するような負の影響を受けると判断された場合は、必ずストアドプロシージャを使用しないでください。

私は、ベストプラクティスに悪を呼んでいる人々からのストアドプロシージャについて長年にわたって冗談を聞いてきました。私が来たという結論は、常に仕事のために適切なツールを使用することです。そして、実行時間とクエリ・プランを比較

EXPLAIN ANALYZE SELECT * FROM items WHERE id NOT IN (
    SELECT item_id FROM excluded_items WHERE user_id = 123 
); 

、その後

EXPLAIN ANALYZE SELECT * FROM user_items(123); 

を:使用していくつかのテストクエリを実行し、変更が正確にパフォーマンスにどのように影響するかを決定するため

。私はあなたがより情報に基づいた決定をすることができると思います。

+0

感謝のエリヤ。私は実際にこのページをリフレッシュしている間にクエリを分析していました:-)これまでのSPは遅いですが、違いはごくわずかです。私は、私が考慮していないパフォーマンスを除いて、何か問題があるかどうかを知ることに本当に興味があると思います。これまでのところ、コンセンサスはあなたの答えに感謝します。 –

1

私はストアドプロシージャの解決策はより乾燥しており、実際には読みやすさが向上すると思います。可能であれば(特にPostgreSQLの強力なルールを使って)ビューを使用することを確かにしていますが、これを表現するうえでより良い方法を考えることはできません。

-2

同じ場所にSQLを置くと、クライアント側も解決できます。たとえば、SQL文字列を構築する機能を作成します。

public string SqlItemsForUser(int iUserId) { 
    return "SELECT * FROM items WHERE id NOT IN (" + 
     "SELECT item_id FROM excluded_items WHERE user_id = " + 
     Convert.ToString(iUserId) + ");"; 
} 

あなたは、90個の場所でこの関数を呼び出すことができますので、あなたは、副問合せを変更する必要があれば、あなただけの一箇所でそれを変更する必要があります。あなたは既に

create view user_items as (
    select i.*, u.id as user_id 
    from (items i cross join users u) 
     left join excluded_items e 
     on (i.id = e.item_id 
     and u.id = e.user_id) 
    where e.item_id is null 
); 

のようなものを

2

てみましたか?私はPostgreSQL 8でそれをテストしました。このビューを使用して、クエリがへの可能性を見つけるためのクエリオプティマイザはあまりにも複雑になる場合が

select * 
    from user_items ui 
    where user_id = 1; 

のような単純なクエリでビューを使用する場合は、参加クロスへのuser_idに条件を引くことが可能である3、 user_idの条件をクロス結合に引き込み、フル・クロス結合が計算された場合でも、クエリ・オプティマイザの一部をparametersと再生して、再度プルインすることができます。