Эффективный результат ограничения набора в оконной функции SQL - PullRequest
0 голосов
/ 19 января 2019

Мой вопрос лучше было бы использовать в качестве комментария к Ограничить набор результатов в функции окна sql , но у меня нет необходимой репутации, чтобы комментировать.

С учетом таблицы перемещенияместоположения транспортных средств, для каждого транспортного средства я хочу найти самое последнее зарегистрированное местоположение (и другие данные о транспортном средстве в то время).Основываясь на ответах на другой вопрос, я могу выполнить запрос вроде:

Определение таблицы:

CREATE TABLE VehiclePositions
(
    Id BIGINT NOT NULL,
    VehicleID  NVARCHAR(12) NULL,
    Timestamp DATETIME NULL,
    PositionX FLOAT NULL,
    PositionY FLOAT NULL,
    PositionZ SMALLINT NULL,
    Speed SMALLINT NULL,
    Heading SMALLINT NULL 
)

Запрос:

select *
from 
    (select 
         *,
         row_number() over (partition by VehicleID order by Timestamp desc) as ranking
     from VehiclePositions) as x
where 
    ranking = 1

Теперь проблема в том, чтоэто делает полное сканирование таблицы.Я думал, что, создав соответствующий индекс, я мог бы избежать этого:

CREATE INDEX idx_VehicPosition ON VehiclePositions(VehicleID, Timestamp);

Однако SQL Server с радостью проигнорирует этот индекс в запросе и все равно выполнит стабильное сканирование.

Примечание: я могу заставить SQL Server использовать индекс, но код довольно уродлив:

DECLARE @ids TABLE (id NVARCHAR(12) UNIQUE)

INSERT INTO @ids 
    SELECT DISTINCT VehicleID 
    FROM VehiclePositions

SELECT ep.* 
FROM VehiclePositions vp
WHERE Timestamp = (SELECT Max(TimeStamp) FROM VehiclePositions vp2 
                   WHERE vp2.VehicleID = vp.VehicleID)
  AND VehicleID IN (SELECT DISTINCT id FROM @ids)

(* * * * * * * * *1020*, потому что, похоже, SQL Server не поддерживает поиск-пропустить оптимизацию. Он все еще предлагает довольно неоптимальный план запроса, который посещает индекс дважды, но, по крайней мере, он не выполняется за линейное время).

Есть ли способ заставить SQL Server работатьинтеллектуальный запрос оконной функции?

Я использую SQL Server 2014 ...

Помощь будет оценена по достоинству

Ответы [ 2 ]

0 голосов
/ 20 января 2019

Пока вы выбираете все транспортные средства из таблицы и выбираете все столбцы (или, по крайней мере, столбцы, которых нет в вашем индексе), я ожидаю, что сканирование таблицы продолжит появляться.

Во многих случаях это будет самый эффективный план запроса. Только если у вас есть несколько строк на транспортное средство (например, несколько страниц), стратегия поиска может быть быстрее.

Если у вас много строк на транспортное средство, возможно, вы захотите разбить таблицу на Timestamp ...

0 голосов
/ 19 января 2019

Что бы я сделал:

  SELECT *
  FROM
     (SELECT  MAX(Timestamp) as maxtime,
             VehicleID 
     FROM VehiclePositions
     GROUP BY VehicleID ) as maxed INNER JOIN 
    (SELECT  Id ,
             VehicleID ,
             Timestamp ,
             PositionX ,
             PositionY,
             PositionZ,
             Speed ,
             Heading 
     FROM VehiclePositions) as vals
       ON maxed.maxtime = vals.Timestamp
      AND maxed.VehicleID = vals.VehicleID

Насколько мне известно, вы не можете обойти свой индекс, сканируемый дважды.

...