简体   繁体   中英

Optimizing a SQL Query which is already doing an index seek

I have a SQL query which is pretty efficient, but I have a feeling it can be improved upon.

It's the 48% cost on the sort after the index seek using IX_thing_time_location that I would hope can be improved upon. I would hate to think that this is the best that can be done with this query. Is there anything else I can do to improve performance in terms of updating the query, changing my indexes, partitioning (I know these doesn't always mean performance gains)?

Here is the execution plan: http://pastebin.com/G4Zi2tnw

I tried to paste it in here, but it's too large.

Index definition:

CREATE NONCLUSTERED INDEX [IX_thing_time_location] ON [dbo].[tippy]
(
    [time_start] ASC,
    [location] ASC
)
INCLUDE (   [id],
    [name],
    [time_end],
    [is_meetup],
    [utc_offset],
    [type],
    [all_day]) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO

Stored procedure:

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

SELECT id, name, latitude, longitude
INTO #templocations
FROM locations
WHERE latitude BETWEEN @minLat AND @maxLat
AND longitude BETWEEN @minLong AND @maxLong
ORDER BY id;

-- This is a container
-- Get all "routes" (containers) within a given lat/long combo
SELECT thing_routes.*
INTO #tempRoutes
FROM thing_routes
WHERE latitude BETWEEN @minLat AND @maxLat
AND longitude BETWEEN @minLong AND @maxLong;


-- Get all things which are in the above containers
SELECT tip.id, tip.name, tip.location, tip.time_start, tip.time_end, tip.is_meetup, 
tip.utc_offset, tip.[type], tip.all_day,
#tempRoutes.id AS route_id, locations.name AS location_name, 
locations.latitude AS latitude, locations.longitude AS longitude
INTO #tempRoute_things
FROM #tempRoutes
INNER JOIN link_thing_routes
ON link_thing_routes.route_id = #tempRoutes.id
INNER JOIN locations
ON locations.id = #tempRoutes.location
INNER JOIN thing AS tip
ON link_thing_routes.thing_id = tip.id;


-- Return the data
SELECT * FROM #tempRoutes


-- Return the data - Add in the things from external_thing_routes
-- Join the two tables from earlier, filtering on time
SELECT tip.id, tip.name, tip.location, tip.time_start, tip.time_end, tip.is_meetup, 
tip.utc_offset, tip.[type], tip.all_day, NULL as route_id, #templocations.name AS location_name,
#templocations.latitude AS latitude, #templocations.longitude AS longitude
FROM #templocations 
INNER MERGE JOIN thing AS tip
ON #templocations.id = tip.location 
WHERE time_start BETWEEN @startTime AND @endTime



SELECT external_thing_routes.thing_id, external_thing_routes.route_id
FROM external_thing_routes

I didnt look at the explain script, but i have bumped into similar problems.

Are the columns on which you sort in the same index as the selection? If you got a query like this:

select * 
from exampletable
where foreignkey = somevalue
order by column1, column2

One of the indexes should be

foreignkey, column1, column2

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM