3

私は SQL (SQLite 3 とそのsqlite3コマンドライン ツールを使用) を学んでいますが、いくつかの方法でいくつかのことを実行できることに気付きました。同じことを行う 3 つのクエリを次に示します。1 つはintersect、もう1 つは 、inner joinおよびを介して実行されます。distinct最後のクエリは 2 番目のクエリと似ていますが、 を介したフィルタリングが組み込まれていますwhere。(最初のものは私が読んでいる本の著者が書いたもので、残りは私自身が書いたものです。)

問題は、これらのクエリのどれが優れているか、そしてその理由は? そして、より一般的には、あるクエリが別のクエリよりも優れていることをどのように知ることができますか? SQL の宣言型の性質にもかかわらず、私が見逃した、またはおそらく SQLite の内部を学ぶべきガイドラインはありますか?

(次の例では、いくつかのテレビ シリーズで言及されている食品の名前を記述するテーブルがあります。Foods_episodesは多対多のリンク テーブルであり、他のテーブルは食品名とエピソード名をシーズン番号と一緒に記述します。シーズン 3..5 のトップ フードだけでなく、フード (すべてのシリーズでの登場回数に基づく) を探しています)

-- task
--     find the all-time top ten foods that appear in seasons 3 through 5
-- schema
--     CREATE TABLE episodes (
--       id integer primary key,
--       season int,
--       name text );
--     CREATE TABLE foods(
--       id integer primary key,
--       name text );
--     CREATE TABLE foods_episodes(
--       food_id integer,
--       episode_id integer );



select f.* from foods f 
inner join 
    (select food_id, count(food_id) as count 
        from foods_episodes 
        group by food_id 
        order by count(food_id) desc limit 10) top_foods 
    on f.id=top_foods.food_id 
intersect 
select f.* from foods f 
    inner join foods_episodes fe on f.id = fe.food_id 
    inner join episodes e on fe.episode_id = e.id 
where
    e.season between 3 and 5 
order by
    f.name; 



select
    distinct f.*
from
    foods_episodes as fe
    inner join episodes as e on e.id = fe.episode_id
    inner join foods as f on fe.food_id = f.id
    inner join (select food_id from foods_episodes
        group by food_id order by count(*) desc limit 10) as lol
        on lol.food_id = fe.food_id
where
    e.season between 3 and 5
order by 
    f.name;



select
    distinct f.*
from
    foods_episodes as fe
    inner join episodes as e on e.id = fe.episode_id
    inner join foods as f on fe.food_id = f.id
where
    fe.food_id in (select food_id from foods_episodes
        group by food_id order by count(*) desc limit 10)
    and e.season between 3 and 5
order by 
    f.name;

-- output (same for these thee):

-- id          name      
-- ----------  ----------
-- 4           Bear Claws
-- 146         Decaf Capp
-- 153         Hennigen's
-- 55          Kasha     
-- 94          Ketchup   
-- 164         Naya Water
-- 317         Pizza     
-- CPU Time: user 0.000000 sys 0.000000
4

2 に答える 2

6

MySQL と同様に、SQLlite には EXPLAIN コマンドがあるようです。select の先頭に EXPLAIN キーワードを追加すると、スキャンされた行数や使用されたインデックスなど、クエリに関する情報が返されます。

http://www.sqlite.org/lang_explain.html

さまざまな選択で EXPLAIN を実行することにより、どのクエリ (およびサブクエリ) が他のクエリよりも効率的であるかを判断できます。

SQLlite のクエリ プランナーと最適化の概要は次のとおりです: http://sqlite.org/optoverview.html

SQLlite3 は、クエリをトレースするためのコールバック関数もサポートしています。ただし、実装する必要があります: http://www.sqlite.org/c3ref/profile.html

于 2012-06-11T19:59:46.437 に答える
1

通常、問題を解決する方法は複数あります。正しい答えが得られた場合、他の唯一の質問は、プロセス/スクリプト/ステートメントを改善する必要があるかどうか、または現在うまく機能しているかどうかです。

通常、SQL には「最善の」方法が存在する場合がありますが、通常、何かを実行するための標準的な最善の方法を見つけることが目標ではありません。プログラムからのニーズと自分の時間を効率的にバランスさせる方法が必要です。数か月を費やすことができます。プロセスを最適化しますが、プロセスが毎週のみ使用され、現在 5 分しかかからない場合、4 分に短縮してもあまり役に立ちません。

時間の制約があるため、正しい答えがある状況 (学校など) から、何かをうまくやり遂げることが目標であり、十分に機能することが完璧に勝る状況に移行するのは奇妙です。理解するのにしばらく時間がかかったものですが、これ以上の答えがあるかどうかはわかりません。視点が少し役立つことを願っています!

于 2012-06-11T21:42:04.743 に答える