我正在开发一个配对比较网站,用户可以在该网站上加载来自另一个网站的电影和等级列表。然后,我的网站随机挑选两部电影并将它们相互匹配,用户从两部电影中选择较好的一部,然后加载一对新电影。这给出了按最佳顺序排序的完整电影列表。
数据库包含三个表;
fm_film_data - 这包含所有导入的电影
fm_film_data(id int(11),
imdb_id varchar(10),
tmdb_id varchar(10),
title varchar(255),
original_title varchar(255),
year year(4),
director text,
description text,
poster_url varchar(255))
fm_films - 这包含与用户相关的所有信息,用户看过哪些电影,用户给出的评分,以及该用户每部电影的输赢信息。
fm_films(id int(11),
user_id int(11),
film_id int(11),
grade int(11),
wins int(11),
losses int(11))
fm_log - 这包含已发生的每一场决斗的记录。
fm_log(id int(11),
user_id int(11),
winner int(11),
loser int(11))
为了选择一对显示给用户,我创建了一个 mySQL 查询来检查日志并随机选择一对。
SELECT pair.id1, pair.id2
FROM
(SELECT part1.id AS id1, part2.id AS id2
FROM fm_films AS part1, fm_films AS part2
WHERE part1.id <> part2.id
AND part1.user_id = [!!USERID!!]
AND part2.user_id = [!!USERID!!])
AS pair
LEFT JOIN
(SELECT winner AS id1, loser AS id2
FROM fm_log
WHERE fm_log.user_id = [!!USERID!!]
UNION
SELECT loser AS id1, winner AS id2
FROM fm_log
WHERE fm_log.user_id = [!!USERID!!])
AS log
ON pair.id1 = log.id1 AND pair.id2 = log.id2
WHERE log.id1 IS NULL
ORDER BY RAND()
LIMIT 1
此查询需要一些时间来加载,在我们的测试中大约需要 6 秒,两个用户各有大约 800 个成绩。
我正在寻找一种优化方法,但仍然限制所有决斗只出现一次。
服务器运行 MySQL 版本 5.0.90-community。
最佳答案
我认为您最好创建一个存储过程/函数,它会在找到有效的一对后立即返回一对。
确保有适当的索引:
fm_films.user_id
(也尝试包括film_id
)fm_log.user_id
(尝试包括获胜者
和失败者
)
DELIMITER $$
DROP PROCEDURE IF EXISTS spu_findPair$$
CREATE PROCEDURE spu_findPair
(
IN vUserID INT
)
BEGIN
DECLARE done BOOLEAN DEFAULT FALSE;
DECLARE vLastFilmID INT;
DECLARE vCurFilmID INT;
DECLARE cUserFilms CURSOR FOR
SELECT id
FROM fm_films
WHERE user_id = vUserID
ORDER BY RAND();
DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done=TRUE;
OPEN cUserFilms;
ufLoop: LOOP
FETCH cUserFilms INTO vCurFilmID;
IF done THEN
CLOSE cUserFilms;
LEAVE ufLoop;
END IF;
IF vLastFilmID IS NOT NULL THEN
IF NOT EXISTS
(
SELECT 1
FROM fm_log
WHERE user_id = vUserID
AND ((winner = vCurFilmID AND loser = vLastFilmID) OR (winner = vLastFilmID AND loser = vCurFilmID))
) THEN
CLOSE cUserFilms;
LEAVE ufLoop;
#output
SELECT vLastFilmID, vCurFilmID;
END IF;
END IF;
END LOOP;
END$$
DELIMITER ;
关于mysql - 关于对比较的 SQL 查询的优化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4606404/