我目前遇到了昂贵的SQL查询的性能问题,我想改进它。
这是查询的样子:
SELECT TOP 50 MovieID
FROM (SELECT [MovieID], COUNT(*) AS c
FROM [tblMovieTags]
WHERE [TagID] IN (SELECT TOP 7 [TagID]
FROM [tblMovieTags]
WHERE [MovieID]=12345
ORDER BY Relevance ASC)
GROUP BY [MovieID]
HAVING COUNT(*) > 1) a
INNER JOIN [tblMovies] m ON m.MovieID=a.MovieID
WHERE (Hidden=0) AND m.Active=1 AND m.Processed=1
ORDER BY c DESC, m.IMDB DESC
我正在尝试为MovieID 12345找到至少有2个匹配标签的电影。
数据库基本方案如下:
每部电影有4到5个标签。我想要一个类似于任何基于标签的电影的电影列表。必须至少匹配2个标签。
此查询导致我的服务器出现问题,因为我在任何给定时间都有数百个并发用户。
我已经根据执行计划建议创建了索引,这使得它更快,但仍然不够。
我能做些什么来加快速度吗?
答案 0 :(得分:1)
我想看看你写的那个查询是否发生了一些不必要的处理。尝试以下查询,让我们知道它是否更快等等,如果它甚至得到相同的数据。
我只是把它扔在一起所以不能保证完美的语法
SELECT TOP 7 [TagID]
INTO #MovieTags
FROM [tblMovieTags]
WHERE [MovieID]=12345
ORDER BY TagID
;cte_movies AS
(
SELECT
mt.MovieID
,mt.TagID
FROM
tblMovieTags mt
INNER JOIN #MovieTags t ON mt.TagId = t.TagId
INNER JOIN tblMovies m ON mt.MovieID = m.MovieID
WHERE
(Hidden=0) AND m.Active=1 AND m.Processed=1
),
cte_movietags AS
(
SELECT
MovieId
,COUNT(MovieId) AS TagCount
FROM
cte_movies
GROUP BY MovieId
)
SELECT
MovieId
FROM
cte_movietags
WHERE
TagCount > 1
ORDER BY
MovieId
GO
DROP TABLE #MovieTags
答案 1 :(得分:1)
我喜欢使用临时表,因为它们可以加快查询速度(如果使用正确)并使其更易于阅读。尝试使用下面的查询,看看它是否加快了它。
中有一些字段(隐藏,imdb)不在您的架构中,所以我们将它们排除在外。此查询可能或可能不是您正在寻找的内容。它的目的是向您展示如何使用临时表来提高性能并提高可读性。可能需要进行一些小的调整。
SELECT TOP 7 [TagID],[MovieTagID],[MovieID]
INTO #MovieTags
FROM [tblMovieTags]
WHERE [MovieID]=12345
SELECT mt.MovieID, COUNT(mt.MovieTagID)
INTO #Movies
FROM #MovieTags mt
INNER JOIN tblMovies m ON m.MovieID=mt.MovieID AND m.Active=1 AND m.Process=1
GROUP BY [MovieID]
HAVING COUNT(mt.MovieTagID) > 1
SELECT TOP 50 * FROM #Movies
DROP TABLE #MovieTags
DROP TABLE #Movies
修改强>
参数化查询
您还希望使用参数化查询,而不是在SQL字符串中连接您的值。查看此short, to the point, blog,了解您应该使用参数化查询的原因。这与临时表方法相结合,可以显着提高您的性能。