PHP / MYSQL,for循环中的NTH术语查询或初始查询后推送id数组后的IN查询更快?

时间:2018-01-10 17:39:07

标签: php mysql performance

我想知道这种逻辑是否会改善查询性能,比如说比较然后检查用户是否喜欢数组中每个元素的帖子并为每个元素触发查询。

相反,我可以将主要ID推送到一个数组,然后对它们执行IN查询,这将减少第15个术语查询,并将其批处理为2个查询,包括初始查询。

我正在使用PHP PDO,MYSQL。

有什么建议吗?我是在正确的轨道上吗? :d

$ items是数据库中的结果集,在这种情况下,它们是用户提出的问题,我在大约140毫秒内得到响应,并且我已经设置了对一次加载多少项的限制

    $questionIds = [];

    foreach ($items as $item) {
        array_push($questionIds, $item->question_id);
    }

    $items = loggedInUserLikesQuestions($questionIds, $items, $user_id);

1 个答案:

答案 0 :(得分:2)

在执行SQL查询时,IN子句肯定更快。但是,一旦IN子句中的项目数(平均)变高,您将只看到显着的实际时钟速度优势。

即使单个更新可能是快速的,速度差异的原因是每个查询的设置,执行,拆除和响应,发送/接收到服务器。当你尽可能快地完成数千(或数百万)这些时,我已经看到,而不是500 /秒,获得200,000 /秒。这可能会给你一些想法。

但是,使用IN子句方法,您需要确保IN子句不会变得太大,并且达到最大查询大小(请参阅variable max_allowed_packet

这是一组简单的函数,它们将自动批处理为每个1000项的IN子句:

<?php

$db = new PDO('...');
$__q = [];
$flushQueue = function() use ($db, &$__q) {
    if ( count($__q) > 0 ) {
        $sanitized_ids = [];
        foreach ( $__q as $id ) { $sanitized_ids[] = (int) $id; }
        $db->query("UPDATE question SET linked = 1 WHERE id IN (". join(',',$sanitized_ids) .")");
        $__q = [];
    }
};
$queuedUpdate = function($question_id) use (&$__q, $flushQueue){
    $__q[] = $question_id;
    if ( count( $__q) > 1000 ) { $flushQueue(); }
};


// Then your code...
foreach ($items as $item) {
    $queuedUpdate($item->question_id);
}
$flushQueue();

显然,如果你在课堂上,你不必使用匿名功能。但上面的内容可以在任何地方使用(假设你在&gt; = PHP 5.3)。