我對PHP和MYSQL真的很陌生,我一個月前都不知道,所以請原諒我的馬虎/糟糕的代碼:)MYSQL&PHP:在PHP while循環中運行INSERT INTO SELECT查詢,運行緩慢
我有我的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,尚未購買的物品清單。然後在返回的每一行(item)上運行一個while循環,在此循環中執行主查詢。
這下一個查詢是從收視率表中獲取信息,其中item_id等於當前正在查詢的item_id,並將其加入到具有正確聯接的預先計算的用戶兼容性表中。
然後,我對評級和兼容性評級運算算法以形成推薦值,然後將推薦item_id和user_id插入到稍後調用的另一個表中。在(item_id,user_id)列上有一個2列唯一鍵,因此在末尾的ON DUPLICATE KEY UPDATE
所以我今天早上寫了這段代碼,對自己很滿意,因爲它確實是我需要的做。
問題是,可以預見,它很慢。在我的測試數據庫中,有5個測試用戶和100個測試項目以及200個評分的隨機分組,它需要2.5秒才能通過while循環。我期待它會變慢,但不會這麼慢。一旦添加了更多的用戶和項目,這真的很難。主要問題是插入...在重複密鑰更新部分,我的磁盤利用率達到100%,我可以告訴我的筆記本電腦的硬盤正在尋求瘋狂。我知道我可能會在生產中使用固態硬盤,但我仍然預計有數千個項目和用戶會遇到大規模問題。
所以我的主要問題在於:任何人都可以提供任何建議,如何優化我的代碼,或完全rejig的東西,以提高速度。我確信在while循環中插入查詢是一個不好的方法,我只是想不出任何其他方式來獲得完全相同的結果
在此先感謝和抱歉,如果我格式化我的問題正確
**警告:** 使用'mysqli'時,應該使用參數化查詢和['bind_param'](http://php.net/manual/en/mysqli-stmt.bind-param.php)將用戶數據添加到您的查詢中。**不要**使用字符串插值來實現此目的,因爲您將創建嚴重的[SQL注入漏洞](http://bobby-tables.com/)。 – tadman 2014-11-06 21:16:16
@fetef FWIW:我已經看到了來自月齡較大的程序員的更糟糕的代碼;) – webnoob 2014-11-06 21:16:54
如果您是PHP的新手,您應該從 [開發框架]開始(http://codegeekz.com/best-php-frameworks對於開發人員/)像[Laravel](http://laravel.com/),這符合你的風格和需求。用超級低級代碼粉碎並不是很有效率。 – tadman 2014-11-06 21:17:01