PHP 内部的连接分解

2024-05-01

我看到一篇关于连接分解的文章。

场景#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 性能:加入分解? https://stackoverflow.com/questions/5385059/myisam-performance-join-decomposition但这没有帮助)


你可以使用 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 并告诉我它不起作用之前,验证所有表和列名称。

在有人开始抱怨速度、缓存和效率之前:我认为这相当高效。您可以使用本机 SQL 选择较小的位,而不是使用 PHP 选择所有数据并循环遍历它。

再次强调,我强烈反对使用 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 的原因。

现在,我记得,你想要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 进行较小的操作,呵呵...

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

PHP 内部的连接分解 的相关文章

  • 如何在 PHP 中将默认日期设置为波斯日期?

    如何在 PHP 中将默认日期设置为波斯日期 说吧 如果我echo这个功能date Y m d 然后它会显示2018 03 05但我想要1396 12 14波斯日期 请检查 http php net manual en intldatefor
  • 为什么 SORT_REGULAR 在 PHP 中产生不一致的结果?

    我正在开发一个类 它使 PHP 中的数组排序变得更容易 并且我一直在使用 SORT 常量 但是行为或SORT REGULAR 默认排序类型 似乎有所不同 具体取决于您在数组中添加项目的顺序 此外 我找不到任何模式来解释为什么会出现这种情况
  • 在 php 和 mysql 中使用 utf8mb4

    我读过 mysql gt 5 5 3 完全支持每个可能的字符 如果您使用编码utf8mb4对于某个表 列http mathiasbynens be notes mysql utf8mb4 http mathiasbynens be note
  • PHP:如何发送电子邮件基础知识

    我想使用 PHP 从本地主机向其他人发送电子邮件 我需要做什么才能做到这一点 例如我需要安装邮件服务器吗 如果我没记错的话 有一种语言不需要邮件服务器来发送电子邮件 这样对吗 PHP ini里面有 邮件功能 如何配置这个 我在网上查了一下
  • 使用 DateTime 类计算日期差异时出错

    我正在尝试使用 DateTime 类 php gt 5 3 来计算 2 个日期的差异 手册中的示例简单明了 我尝试了该示例并且效果很好 但如果改变开始和结束日期 就会出现问题 this gt start date 2011 03 01 th
  • 使用来自另一个的 SELECT 更新表,但字段为 SUM(someField)

    基本上我有这样的事情 UPDATE Table SET Table col1 other table col1 FROM Table INNER JOIN other table ON Table id other table id 问题是
  • Laravel 类邮件程序不存在

    我将应用程序从 5 更新到 5 2 现在 当我调用 Mail send 时 它会返回一个异常 Class mailer 不存在 Mail send emails mail data gt content function m use to
  • 无法在 PHPUnit 中使用数据提供程序运行单个测试

    使用命令行运行测试时遇到问题 如果我像这样运行 phpunit phpunit no configuration filter testAdd DataTest DataProviderTest php 效果很好 但是我们使用正则表达式来准
  • 在 BIRT 中输入参数后更新数据集查询

    在 BIRT 报告设计中传递参数后 如何更改或更新数据集的查询 详细说明 我有一个如下所示的查询 WHERE 该参数标记可以保存不同的值 在用户输入参数后 它看起来像这样 例如 WHERE column name 1 or WHERE co
  • 我应该使用排队系统来处理付款吗?

    我在用着Slim https www slimframework com和这个结合Stripe 的 PHP 库 https stripe com docs api php在我的应用程序中处理付款 一切都很好 但是直到最近 我在我的系统中发现
  • 如何检查一个值是否已经存在以避免重复?

    我有一个 URL 表 但我不想要任何重复的 URL 如何使用 PHP MySQL 检查给定 URL 是否已在表中 如果您不想重复 可以执行以下操作 添加唯一性约束 use REPLACE http dev mysql com doc ref
  • 除括号之间的内容外,所有内容均小写

    考虑以下字符串 LoReM FOO IPSUM dolor BAR Samet fooBar 我正在寻找一种方法来小写所有内容 除了 brackets 之间的内容应该被忽略 所以期望的输出是 lorem FOO ipsum dolor BA
  • ODBC 链接表中突然开始出现写入冲突消息

    我有一个 mySQL 数据库 用于跟踪我们的项目并驱动我们的网站显示其信息 为了方便更新数据库 我设置了一个使用 ODBC 连接 MySQL ODBC 5 1 来编辑数据的访问数据库 过去几个月一直运行良好 没有出现任何问题 然而 昨晚用户
  • 如何在 PHP >= 5.3 严格模式下向对象添加属性而不产生错误

    这必须很简单 但我似乎找不到答案 我有一个通用的 stdClass 对象 foo没有属性 我想添加一个新属性 bar尚未定义 如果我这样做 foo new StdClass foo gt bar 1234 严格模式下的 PHP 会抱怨 将属
  • 有关于 PHP 中的 V8JS 的文档吗?

    有没有关于V8JS的文档 我是否只需要标准 PHP 或一些扩展即可使用 V8JS 我将非常感谢有关 PHP 中的 V8JS 的任何信息 要求 PHP 5 3 3 和 V8 库和标头安装在正确的路径中 Install http www php
  • Mac OSX 10.6 上的 Python mysqldb 不工作

    我正在使用 Python 2 7 并尝试让 Django 项目在 MySQL 后端运行 我已经下载了 mysqldb 并按照此处的指南进行操作 http cd34 com blog programming python mysql pyth
  • 如何更改phpmyadmin MySQL的IP地址?

    我在 xampp 中更改了 apache 的 IP 地址 但无法连接到 MySQL 我认为问题是我的 apache 不在我的数据库的同一网络上 我的 apache 位于 192 168 1 10 而我的 MySQL 位于 127 0 0 1
  • SimpleXML插入处理指令(样式表)

    我想集成一个XSL文件在一个XML给我的字符串php CURL命令 我试过这个 output XML gived me by curl option hotel simplexml load string output hotel gt a
  • 根据最大值连接表

    这是我正在谈论的内容的一个简化示例 Table students exam results id name id student id score date 1 Jim 1 1 73 8 1 09 2 Joe 2 1 67 9 2 09 3
  • 在 Django 查询中使用 .extra(select={...}) 引入的值上使用 .aggregate() ?

    我正在尝试计算玩家每周玩游戏的次数 如下所示 player game objects extra select week WEEK games game date aggregate count Count week 但姜戈抱怨说 Fiel

随机推荐