2016-05-13 16 views
1

結果: 私は三つの方法を使用しました:1は、それぞれ(鉱山)に参加カウントが参加 - 最適化

  1. 三つのサブクエリ、どこでフィルタリング
  2. 三つのサブクエリ、ノー参加し、私は、「説明」および各クエリがしなければならない作業を説明し、「プロファイリング」と以下の結果は驚くべきことではありませんでしたし、いくつかの統計を作った

(SlimsGhost)

  • トリプル参加(Solarflare):stats

    相対結果:

    1. 100%
    2. 79%
    3. 1715パーセント

      three sub queries with simple join three sub queries with where clauseone query with triple join

    原文

    アイデアは、毎回同じPKを使用して4つのテーブルを結合し、各結合が別々に与える行の数を数えることです。

    明らかな答えは、サブクエリを使用して各結合を個別に実行することです。

    ただし、1つのクエリで行うことはできますか?より効率的でしょうか?

    select "LES CIGARES DU PHARAON" as "Titre", 
          (select count(payalb.idPays) 
          from album alb 
            left join pays_album payalb using (idAlb) 
          where alb.titreAlb = "LES CIGARES DU PHARAON") as "Pays", 
          (select count(peralb.idPers) 
          from album alb 
            left join pers_album peralb using (idAlb) 
          where alb.titreAlb = "LES CIGARES DU PHARAON") as "Personnages", 
          (select count(juralb.idJur) 
          from album alb 
            left join juron_album juralb using (idAlb) 
          where alb.titreAlb = "LES CIGARES DU PHARAON") as "Jurons" 
    ; 
    +------------------------+------+-------------+--------+ 
    | Titre     | Pays | Personnages | Jurons | 
    +------------------------+------+-------------+--------+ 
    | LES CIGARES DU PHARAON | 3 |   13 |  50 | 
    +------------------------+------+-------------+--------+ 
    

    テーブルアルバム行:22

    テーブルpays_album行:45

    テーブルpersonnage_album行:100

    テーブルjuron_album行:1704

    ここに私が試したものです。

    select alb.titreAlb as "Titre", 
         sum(case when alb.idAlb=payalb.idAlb then 1 else 0 end) "Pays", 
         sum(case when alb.idAlb=peralb.idAlb then 1 else 0 end) "Personnages", 
         sum(case when alb.idAlb=juralb.idAlb then 1 else 0 end) "Jurons" 
    from album alb 
          left join pays_album payalb using (idAlb) 
          left join pers_album peralb using (idAlb) 
          left join juron_album juralb using (idAlb) 
    where alb.titreAlb = "LES CIGARES DU PHARAON" 
    group by alb.titreAlb 
    ; 
    +------------------------+------+-------------+--------+ 
    | Titre     | Pays | Personnages | Jurons | 
    +------------------------+------+-------------+--------+ 
    | LES CIGARES DU PHARAON | 1950 |  1950 | 1950 | 
    +------------------------+------+-------------+--------+ 
    

    それは完全な結合テーブルの行の合計数をカウントし、...(= 3 * 13 * 50 1950)

    スキーマ:あなたがしたい場合https://github.com/LittleNooby/gbd2015-2016/blob/master/tintin_description

    https://github.com/LittleNooby/gbd2015-2016/blob/master/tintin_schema.png

    テーブルの内容

    にdb_init:https://github.com/LittleNooby/gbd2015-2016/blob/master/tintin_ok.mysql

  • +0

    アルバムテーブルのサンプルデータを見たいと思います。なぜあなたはこれをしたいのですか? –

    +0

    を最適化し、後で使用できるかどうかを知ることができます。 (明らかにこのデータベースはエクササイズ用です) "テーブルの内容"へのリンクを投稿するために投稿を編集しました –

    +0

    テキストファイルにリンクする代わりにsqlfiddleを作成した場合に役立ちます。 – Barmar

    答えて

    2

    最適化の目的で、大まかに言えば、以下に参加することです。実際、できるだけ少ない数の行にできるだけ参加するようにしてください。追加の結合を追加すると、コストを追加するのではなく、コストを増やすことになります。 mysqlは基本的に大きな掛け算行列を生成するだけなので、インデックスやその他のものによって最適化されています。

    しかし、あなたの質問に答えるには、テーブルに一意のキーがあり、idalbがアルバムの一意のキーであると仮定すると、1つの大きな結合で数えることは実際には可能です。次に、とだけにして、あなたはあなたのコードにそれが似て行うことができます:PrimaryKeyFieldsが結合されたテーブルの主キーフィールドを表します

    select alb.titreAlb as "Titre", 
         count(distinct payalb.idAlb, payalb.PrimaryKeyFields) "Pays", 
         count(distinct peralb.idAlb, peralb.PrimaryKeyFields) "Personnages", 
         count(distinct juralb.idAlb, juralb.PrimaryKeyFields) "Jurons" 
    from album alb 
    left join pays_album payalb using (idAlb) 
    left join pers_album peralb using (idAlb) 
    left join juron_album juralb using (idAlb) 
    where alb.titreAlb = "LES CIGARES DU PHARAON" 
    group by alb.titreAlb 
    

    は(あなたがそれらを見ています)。

    Distinctは、他の結合がカウントに与える影響を削除します。しかし残念ながら、一般的に、distinctは、ジョインがコストに及ぼす影響を取り除きません。

    テーブルのすべての(idAlb + PrimaryKeyFields)フィールドをカバーするインデックスがある場合は、元のソリューションと同じ速さでも(並べ替えを行わないようにdistinctを最適化できるため)あなたが考えていたものに近い(すべてのテーブル/インデックスを1回歩いて)。しかし、正常または最悪のケースでは、SlimGhostのような合理的な解決策よりも悪い結果を出すはずです。なぜなら、それは最適な戦略を見つけることが疑わしいからです。しかし、それを使って遊んで、説明をチェックして(そして結果を投稿する)、おそらくmysqlは何か狂ったことをします。

    1

    を限り「デシベルのための最低の仕事」として、私は以下をl正しいと少ないの両方だと思うそれを再生するには再生しますスキーマの一般的なI/Oあなたが説明計画(期待と実際)を見ない限り、確かに分かりません。

    まだ、私はこれを試してみることをお勧めします - 元のクエリは4回アクセスする必要がありますが、 "alb"テーブルには1回しかアクセスしません(1回は "ベース"アルバムレコードを取得し、サブクエリ)。

    select alb.titreAlb as "Titre", 
        (select count(*) from pays_album t2 where t2.idAlb = alb.idAlb) "Pays", 
        (select count(*) from pers_album t2 where t2.idAlb = alb.idAlb) "Personnages", 
        (select count(*) from juron_album t2 where t2.idAlb = alb.idAlb) "Jurons" 
    from album alb 
    where alb.titreAlb = "LES CIGARES DU PHARAON" 
    
    関連する問題