2011-12-20 2 views
3

Join分解についての記事があります。PHP内で分解に参加する

シナリオ#1(良くない):

Select * from tag 
Join tag_post ON tag_post.tag_id=tag.id 
Join post ON tag_post.post_id=post.id 
Where tag.tag='mysql' 

SCENARIO#2(良い):

Select * from tag where tag='mysql' 

Select * from tag_post Where tag_id=1234 

Select * from post where post.id in (123,456,9098,545) 

それは特別に多くの理由のためにシナリオ#2に固執することが示唆されましたキャッシング。 質問は、アプリケーション内での参加方法です。 PHP を個別に取得した後、そのサンプルを教えていただけますか? (私はMyISAM Performance: Join Decomposition? を読みましたが、それは助けにはならなかった)

答えて

2

(私はあなたの質問を理解している場合)は、SQLの副選択を使用することができます。 PHPの使用は、SQLはすべての機能を備えていますが、むしろ奇妙です。

SELECT * 
FROM `post` 
WHERE `id` IN (
    SELECT `post_id` 
    FROM `tag_post` 
    WHERE `tag_id` = (
     SELECT `tag_id` 
     FROM `tag` 
     WHERE `tag` = 'mysql' 
    ) 
) 

私はあなたのデータベースの構造がどのように見えるかわからないんだけど、これはあなたが始める必要があります。これは、SQLの導入のほんの一部です。クエリ内のクエリ。副選択の結果を使用してデータを選択することができます。

このSQLをコピーして動作していないことを伝える前に、すべてのテーブル名とカラム名を確認してください。

誰もがスピードとキャッシングと効率について泣き出し始める前に、これはかなり効率的だと思います。 PHPを使用してすべてのデータを選択してループするのではなく、ネイティブSQLを使用して使用する小さなビットを選択するだけで済みます。

また、特定のデータを取得するためにPHPを使用することを強くお勧めします。 SQLだけで十分です。


編集:これは、あなたが上記のスクリプトの長さを見れば

// dummy results 

// table tag 
$tags = array(
    // first record 
    array(
     'id' => 0, 
     'tag' => 'mysql' 
    ), 
    // second record 
    array(
     'id' => 1, 
     'tag' => 'php' 
    ) 
    // etc 
); 

// table tag_post 
$tag_posts = array(
    // first record 
    array(
     'id'  => 0, 
     'post_id' => 0, // post #1 
     'tag_id' => 0 // has tag mysql 
    ), 
    // second record 
    array(
     'id'  => 1, 
     'post_id' => 1, // post #2 
     'tag_id' => 0 // has tag mysql 
    ), 
    // second record 
    array(
     'id'  => 2, 
     'post_id' => 2, // post #3 
     'tag_id' => 1 // has tag mysql 
    ) 
    // etc 
); 

// table post 
$posts = array(
    // first record 
    array(
     'id'  => 0, 
     'content' => 'content post #1' 
    ), 
    // second record 
    array(
     'id'  => 1, 
     'content' => 'content post #2' 
    ), 
    // third record 
    array(
     'id'  => 2, 
     'content' => 'content post #3' 
    ) 
    // etc 
); 

// searching for tag 
$tag = 'mysql'; 
$tagid = -1; 
$postids = array(); 
$results = array(); 

// first get the id of this tag 
foreach($tags as $key => $value) { 
    if($value['tag'] === $tag) { 
     // set the id of the tag 
     $tagid = $value['id']; 

     // theres only one possible id, so we break the loop 
     break; 
    } 
} 

// get post ids using the tag id 
if($tagid > -1) { // verify if a tag id was found 
    foreach($tag_posts as $key => $value) { 
     if($value['tag_id'] === $tagid) { 
      // add post id to post ids 
      $postids[] = $value['post_id']; 
     } 
    } 
} 

// finally get post content 
if(count($postids) > 0) { //verify if some posts were found 
    foreach($posts as $key => $value) { 
     // check if the id of the post can be found in the posts ids we have found 
     if(in_array($value['id'], $postids)) { 
      // add all data of the post to result 
      $results[] = $value; 
     } 
    } 
} 

:ここにすべてのデータを含むいくつかの多次元配列を持っていると仮定すると、スクリプト

です正確に私がSQLに固執する理由。

ここで思い出したように、PHPを使用してjoinにしたかったのですが、SQLで実行していました。これは結合ではなく、いくつかの配列を使って結果を得ることです。私は知っていますが、参加は時間の無駄であり、すべての結果をそのまま残しておくよりも効率的ではありません。


編集:21-12-12

以下のコメントの結果として、私は少しのベンチマークをやったし、結果は非常に素晴らしいです:

DATABASE RECORDS: 
tags:   10 
posts:   1000 
tag_posts:  1000 (every post has 1 random tag) 

Selecting all posts with a specific tag resulted in 82 records. 

SUBSELECT RESULTS: 
run time:      0.772885084152 
bytes downloaded from database: 3417 

PHP RESULTS: 
run time:      0.086599111557 
bytes downloaded from database: 48644 



Please note that the benchmark had both the application as the database on the 
same host. If you use different hosts for the application and the database layer, 
the PHP result could end up taking longer because naturally sending data between 
two hosts will take much more time then when they're on the same host. 

でも副選択かかわらず、多くのデータを返すことなく、要求の継続時間はほぼ10倍長くなります...

私はこれらの結果を期待したことがありませんので、私は確信して私はパフォーマンスはしかし、私はまだ笑小さな操作のためにSQLを使用しますが重要であることを知ったとき、私は確かにこの情報を使用します...

+0

TNXの男、私は副選択について知っていますが、記事のポイントは、MySQLに参加するのではなく、アプリ内のさまざまな選択肢に参加することでした。 – ALH

+0

なぜSQLはあなたが必要とするすべてのツールを提供するときあなたのアプリでそれをしたいですか? –

+0

**高性能MySQL **本の言うとおり:マルチテーブル結合の代わりに複数のシングルテーブルクエリを実行し、アプリケーションで結合を実行することで結合を分解することができます! – ALH

関連する問題