php - MYSQL&PHP : running an INSERT INTO SELECT query within a PHP while loop, 运行缓慢

标签 php mysql performance

我真的是 php 和 MYSQL 的新手,一个月前我对这两者都一无所知,所以请原谅我草率/糟糕的代码:)

我的 PHP 中有以下代码:

$starttime = microtime(true);
$q_un = 'SELECT i.id AS id
            FROM items i 
            WHERE i.id NOT IN (SELECT item_id FROM purchased_items WHERE user_id=' . $user_id . ')';
$r_un = mysqli_query($dbc, $q_un);
if (mysqli_num_rows($r_un) > 0) {
while ($row_un = mysqli_fetch_array($r_un, MYSQLI_ASSOC)) {
    $item_id = $row_un['id'];
    $q_rec = 'INSERT INTO compatibility_recommendations (
                `recommendation`,
                `user_id`,
                `item_id`)
                SELECT
                    ((SUM(a.rating*(a.compat-80)))/(SUM(a.compat-80)))*10 AS rec,
                    a.user_id AS user_id,
                    a.item_id AS item_id
                FROM
                    (SELECT r.rating AS rating, 
                        c.user2_id AS rater, 
                        c.user1_id AS user_id, 
                        c.compatibility AS compat, 
                        r.item_id AS item_id 
                    FROM ratings r
                    RIGHT JOIN compatibility_ratings c ON r.user_id=c.user2_id
                    WHERE c.user1_id=' . $user_id . ' AND r.item_id=' . $item_id . ' AND c.compatibility>80) a
                ON DUPLICATE KEY UPDATE
                    recommendation = VALUES(recommendation)';
    $r_rec = mysqli_query($dbc, $q_rec);
}
}
$endtime = microtime(true);
$duration = $endtime - $starttime;</code>

第一个查询选择当前用户 $user_id 尚未购买的项目列表。然后我在返回的每一行(项目)上运行一个 while 循环,在这个循环中执行主查询。

下一个查询从评级表中获取信息,其中 item_id 等于正在查询的当前 item_id,并使用右连接将其连接到预先计算的用户兼容性表。

然后我对ratings和compatibility ratings进行运算,形成一个推荐值,然后将recommendation,item_id和user_id插入到另一个表中,稍后调用。在 (item_id,user_id) 列上有一个 2 列唯一键,因此最后是 ON DUPLICATE KEY UPDATE

所以我今天早上写了这段代码,我对自己很满意,因为它完全满足了我的需要。

问题是,不出所料,它很慢。在我的测试数据库中,有 5 个测试用户和 100 个测试项目以及随机分类的 200 个评级,运行 while 循环需要 2.5 秒。我原以为它会很慢,但没有这么慢。一旦添加了更多的用户和项目,它真的会很挣扎。主要问题是插入...在重复 key 更新部分,我的磁盘利用率达到 100%,我可以看出我的笔记本电脑的 HDD 正在疯狂地寻找。我知道我可能会在生产中使用 SSD,但我仍然预计会有数千个项目和用户出现大规模问题。

所以我的主要问题是:任何人都可以就如何优化我的代码或完全重新调整以提高速度提出任何建议。我确信在 while 循环中插入查询是一种糟糕的方法,我只是想不出任何其他方法来获得完全相同的结果

提前致谢,如果我的问题格式不正确,我深表歉意

最佳答案

$starttime = microtime(true);
$q_un = "

 INSERT INTO compatibility_recommendations 
 (recommendation
 ,user_id
 ,item_id
 )
 SELECT ((SUM(a.rating*(a.compat-80)))/(SUM(a.compat-80)))*10 rec
      , a.user_id 
      , a.item_id 
   FROM
      ( SELECT r.rating rating
             , c.user2_id rater
             , c.user1_id user_id
             , c.compatibility compat
             , r.item_id 
          FROM compatibility_ratings c
          JOIN ratings r
            ON r.user_id = c.user2_id

          JOIN items i
            ON i.id = r.item_id

          LEFT
          JOIN purchased_items p
            ON p.item_id = i.id
           AND p.user_id = $user_id

         WHERE c.user1_id =  $user_id
           AND c.compatibility > 80
           AND p.item_id IS NULL
      ) a
 GROUP BY a.item_id
 ON DUPLICATE KEY UPDATE recommendation = VALUES(recommendation);

 ";

$r_rec = mysqli_query($dbc, $q_rec);
}
}
$endtime = microtime(true);
$duration = $endtime - $starttime;</code>

要进一步改进,我们确实需要查看正确的 DDL 和上面 SELECT 的 EXPLAIN。

关于php - MYSQL&PHP : running an INSERT INTO SELECT query within a PHP while loop, 运行缓慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26789524/

相关文章:

PHP - 单选按钮未在 MySQL DB 上发送值

mysql - 更改 IP 地址后由于 DEFINER 错误无法更改 MySQL 功能

30亿关系数据库的SQL数据库架构设计

performance - 使用谷歌托管的 jQuery-ui 或自托管自定义下载的 jQuery UI?

php - 当用户单击提交按钮时,如何防止退出时出现 JavaScript 警报

php - jQuery 使用 PHP 脚本更新 Div

C# 向 mysql 发送错误参数

php - 创建 View 还是使用 innerjoins?

PHP/MySQL : Replace multiple queries

php - 当访问者从谷歌搜索到我的网站时,我如何获得搜索词?