【发布时间】:2014-11-06 21:15:00
【问题描述】:
我真的是 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,并将其加入到预先计算好的用户兼容性表中。
然后我对评分和兼容性评分进行算术运算以形成推荐值,然后将推荐值、item_id 和 user_id 插入到另一个表中以供稍后调用。 (item_id,user_id) 列上有一个 2 列唯一键,因此最后是 ON DUPLICATE KEY UPDATE
所以我今天早上写了这段代码,对自己很满意,因为它完全符合我的需要。
问题在于,可以预见的是,它很慢。在我的测试数据库中,有 5 个测试用户和 100 个测试项目以及随机分类的 200 个评分,运行 while 循环需要 2.5 秒。我原以为它会很慢,但没有这么慢。一旦添加了更多用户和项目,它真的会很困难。主要问题在于插入...在重复密钥更新部分,我的磁盘利用率达到 100%,我可以告诉我笔记本电脑的硬盘正在疯狂寻找。我知道我可能会在生产中使用 SSD,但我仍然预计会有数千个项目和用户出现重大规模问题。
所以我的主要问题是:任何人都可以就如何优化我的代码或完全重新调整以提高速度提供任何建议。我确信在 while 循环中插入查询是一种糟糕的方法,我只是想不出任何其他方法来获得完全相同的结果
提前感谢,如果我的问题格式不正确,我们深表歉意
【问题讨论】:
-
警告: 使用
mysqli时,您应该使用参数化查询和bind_param将用户数据添加到您的查询中。 请勿使用字符串插值来完成此操作,因为您将创建严重的SQL injection bugs。 -
@fetef FWIW:我见过一个月大的程序员写的更糟糕的代码;)
-
如果您是 PHP 新手,您应该从适合您的风格和需求的 development framework 开始,例如 Laravel。用超低级代码粉碎并不是很有效率。
-
如果您使用 php 框架,大多数时候您的查询将通过它内置的数据库函数进行优化。对于初学者,Codeigniter 非常容易学习和实施。
-
@Angelo - 我还没有看到可以优化数据库查询的框架。您通常会看到抽象库的性能下降。
标签: php mysql performance