присоединиться к разложению внутри PHP - PullRequest
4 голосов
/ 20 декабря 2011

Мне попалась статья о разложении Join.

СЦЕНАРИЙ № 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'

СЦЕНАРИЙ № 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: присоединиться к разложению? , но это не помогло)

1 Ответ

3 голосов
/ 20 декабря 2011

Вы МОЖЕТЕ использовать подвыбор 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 - это все, что вам нужно.


edit: вот ваш сценарий

Предположим, у вас есть несколько многомерных массивов, содержащих все данные:

// 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.

Теперь, насколько я помню, вы хотели join использовать PHP, а не делать это в 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 для небольших операций, хе-хе ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...