爲了最大限度地減少鎖定在帖子表上的時間,我們可以將結果預先聚合到一個臨時表中,然後從中執行更新。
舉個例子:
DROP TEMPORARY TABLE IF EXISTS `__post_last_day_counts__`
;
CREATE TEMPORARY TABLE `__post_last_day_counts__`
(post_id BIGINT NOT NULL COMMENT 'pk'
, likes_last_day BIGINT NOT NULL
, views_last_day BIGINT NOT NULL
, PRIMARY KEY (post_id)
) ENGINE=InnoDB
;
INSERT INTO `__post_last_day_counts__`
(post_id
, likes_last_day
, views_last_day
)
SELECT p.post_id
, IFNULL(lc.likes_last_day,0) AS likes_last_day
, IFNULL(vc.views_last_day,0) AS views_last_day
FROM post p
LEFT
JOIN (SELECT pl.post_id
, COUNT(pl.post_id) AS likes_last_day
FROM post_like pl
WHERE pl.date > ('$current_date' - INTERVAL 1 DAY)
) lc
ON lc.post_id = p.post_id
LEFT
JOIN (SELECT pv.post_id
, COUNT(pv.post_id) AS views_last_day
FROM post_view pv
WHERE pv.date > ('$current_date' - INTERVAL 1 DAY)
) vc
ON vc.post_id = p.post_id
;
隨着臨時表的數量,我們可以更新後的表...
UPDATE post t
JOIN `__post_last_day_counts__` s
ON s.post_id = t.id
SET t.likes_last_day = s.likes_last_day
, t.views_last_day = s.views_last_day
;
和清理...
DROP TEMPORARY TABLE IF EXISTS `__post_last_day_counts__`
;
總的來說,這可能是較慢的,但它可能會最小化時間量t UPDATE語句包含鎖。
注意:臨時表中的post_id
列的數據類型應與post
表中的post_id
的數據類型匹配。我只是猜測。
我們假設post_id
是張貼表的主鍵(或唯一鍵)。
確保選中合適的指標可供選擇:
... on post_view (post_id, date)
... on post_like (post_id, date)
使用EXPLAIN看執行計劃,目前正在執行的操作和正在使用的索引。 (我們希望在Extra列中看到「在組中使用索引」。)
您是否對這些列有索引? –
在phpMyAdmin中運行查詢並在開始時(即在UPDATE之前)添加EXPLAIN。用這個輸出更新你的問題.. – Chris