优化SQL SP,避免临时表

时间:2014-04-29 23:33:12

标签: sql sql-server performance stored-procedures processing-efficiency

我有一个现在表现非常糟糕的SP。我在键列中有一些索引,但是SP的速度大约是14秒,可以拉出5k行,我希望它能够低于秒。我认为它与我在那里的临时表的数量有关,但是我不确定如何避免它们给出我需要访问SP中各个地方的数据。

虽然我已经设置了索引和内容,但请建议您认为可以提高性能的任何内容,我宁愿被告知做我已经做过的事情,而不是被告知重要的事情! :)

CREATE PROCEDURE [dbo].[GetPlacesByLatLong]
@minLat FLOAT,
@maxLat FLOAT,
@minLong FLOAT,
@maxLong FLOAT,
@startTime BIGINT,
@endTime BIGINT
AS

SELECT Place_routes.*
INTO #tempRoutes
FROM Place_routes
WHERE latitude BETWEEN @minLat AND @maxLat
AND longitude BETWEEN @minLong AND @maxLong


SELECT Place.*, #tempRoutes.id AS route_id
INTO #tempRoute_Places
FROM #tempRoutes
INNER JOIN link_Place_routes
ON link_Place_routes.route_id = #tempRoutes.id
INNER JOIN Place ON link_Place_routes.Place_id = Place.id
WHERE latitude BETWEEN @minLat AND @maxLat
AND longitude BETWEEN @minLong AND @maxLong

SELECT * 
INTO #tempLocations 
FROM locations 
WHERE latitude BETWEEN @minLat AND @maxLat
AND longitude BETWEEN @minLong AND @maxLong

SELECT * INTO #tempPlaces FROM (
SELECT * FROM (
SELECT Place.*, 0 as route_id
FROM #tempLocations
INNER JOIN Place
ON #tempLocations.id = Place.location 
WHERE time_start BETWEEN @startTime AND @endTime
UNION 
SELECT #tempRoute_Places.* FROM #tempRoute_Places
) AS blah
UNION
SELECT * FROM (
SELECT Place.*, 0 as route_id
FROM #tempLocations
INNER JOIN Place
ON #tempLocations.id IN (SELECT #tempRoute_Places.location FROM #tempRoute_Places)
WHERE time_start BETWEEN @startTime AND @endTime
UNION 
SELECT #tempRoute_Places.* FROM #tempRoute_Places
) AS blah
WHERE time_start BETWEEN @startTime AND @endTime
OR route_id <> 0
) AS blah2

ORDER BY id


SELECT * FROM #tempRoutes

SELECT * FROM #tempPlaces
UNION
SELECT external_Place_routes.Place_id, null, null, null, null, null, null, null, null, null, null, null, null, external_Place_routes.route_id, null, null FROM external_Place_routes
SELECT * FROM #tempLocations
WHERE id IN (SELECT location FROM #tempPlaces)
SELECT * FROM Place_images 
WHERE Place_id in ( SELECT id FROM #tempPlaces )
ORDER BY Place_id

SELECT link_Place_types.Place_id,[types].*
FROM link_Place_types 
INNER JOIN [types] 
ON [types].id = link_Place_types.type_id
WHERE Place_id in ( SELECT id FROM #tempPlaces )
ORDER BY link_Place_types.Place_id

2 个答案:

答案 0 :(得分:2)

您案例中的临时表可能对性能有所帮助。

立即弹出的三件事:

  1. 永远不要在生产代码中使用SELECT *。尝试将选择列表缩小到您真正需要的列 - 更少的数据随机播放,然后您甚至可以创建覆盖索引。
  2. ORDER BY id语句中删除SELECT * INTO #tempPlaces,它没有用处并引入排序(或可能影响索引选择)
  3. 确保参数的数据类型与列的数据类型匹配。否则,隐式转换可能会阻止使用索引(谓词列上有索引,不是吗?)。
  4. 对于其他任何事情我们都必须看到执行计划。

答案 1 :(得分:0)

这可能会有所帮助:

  SELECT * INTO #tempPlaces FROM

在以下几个地方包含以下内容。

WHERE time_start BETWEEN @startTime AND @endTime

也许将它留在本声明末尾的位置,但将其从联合声明中删除。

SELECT * INTO #tempPlaces FROM (
SELECT * FROM (
SELECT Place.*, 0 as route_id
FROM #tempLocations
INNER JOIN Place
ON #tempLocations.id = Place.location 
UNION 
SELECT #tempRoute_Places.* FROM #tempRoute_Places
) AS blah
UNION
SELECT * FROM (
SELECT Place.*, 0 as route_id
FROM #tempLocations
INNER JOIN Place
ON #tempLocations.id IN (SELECT #tempRoute_Places.location FROM #tempRoute_Places)
UNION 
SELECT #tempRoute_Places.* FROM #tempRoute_Places
) AS blah
WHERE time_start BETWEEN @startTime AND @endTime
OR route_id <> 0
) AS blah2