У меня есть два набора измерений Земли из спутниковых данных, каждый с полями времени (mjd для средней юлианской даты) и географическими положениями (GeoPoint, spacial), и я ищу совпадения между двумя наборами, чтобы их время совпадало с порогом 3 часа (или. 125 дней) и их расстояния в пределах 200 км друг от друга.
Я сделал индексы для полей mjd как для таблиц, так и для пространственных таблиц.
Когда я просто включаю ограничение по времени, база данных вычисляет 100 000 совпадений за 8 секунд и вычисляет расстояния для всех 100 000 совпадений за это время. Запрос выглядит так:
select top 100000 h.Time, m.Time, h.GeoPoint.STDistance(m.GeoPoint)/1000.0
from L2V5.dbo.header h join L2.dbo.MLS_Header m
on h.mjd between m.mjd-.125 and m.mjd+.125
option( table hint ( h, index(ix_MJD) ), table hint( m, index(ix_MJD) ) )
И выполненный план это:
При сортировке 9 расстояний были меньше 200 км, поэтому есть совпадения. Проблема в том, что когда я добавляю ограничение расстояния и запускаю его,
select top 10 h.Time, m.Time, h.GeoPoint.STDistance(m.GeoPoint)/1000.0
from L2V5.dbo.header h join L2.dbo.MLS_Header m
on h.mjd between m.mjd-.125 and m.mjd+.125
and h.GeoPoint.STDistance(m.GeoPoint)<200000
option( table hint ( h, index(ix_MJD) ), table hint( m, index(ix_MJD) ) )
это уходит в течение длительного времени. Очевидно, что за 8 секунд он может найти 100 000 временных матчей, 9 из которых были на расстоянии менее 200 км, поэтому оптимизатор должен попробовать что-то неоптимальное. План выглядит аналогично приведенному выше с фильтром по расстояниям (я предполагаю).
Я могу заставить использование пространственного индекса с этим:
select top 5 h.Time, m.Time, h.GeoPoint.STDistance(m.GeoPoint)/1000.0
from L2V5.dbo.header h join L2.dbo.MLS_Header m
on h.GeoPoint.STDistance(m.GeoPoint)<200000
and h.mjd between m.mjd-.125 and m.mjd+.125
option( table hint ( h, index(ix_MJD), index(ix_GeoPoint) ), table hint( m, index(ix_MJD) ) )
что затем занимает 3 минуты, чтобы найти 5 совпадений.
Как мне сказать оптимизатору запросов использовать сначала поиск по индексу MJD, а затем - по пространственному индексу (или это то, что он уже делает), и есть ли способ помочь ему, сказав, сколько совпадений ожидать? Если он может вычислить 100 000 совпадений с расстояниями за 8 секунд, у которых 9 меньше 200 км, разве добавление пространственного индекса не сделает его быстрее, а не медленнее?
Спасибо за любые другие советы или идеи.
РЕДАКТИРОВАТЬ: Чтобы ответить на вопрос, как план выглядит без намеков, это (и это занимает вечность):
Также стоит упомянуть, что в одной таблице почти 1 млн записей, а в другой - 8 млн.
источник
Ответы:
Проблема в том, что он может (и, зная пространственные индексы, вероятно, будет) предполагать, что пространственный фильтр будет намного более избирательным, чем временной фильтр.
Но если у вас есть несколько миллионов записей в пределах 200 км, то это может быть значительно хуже.
Вы просите его найти записи в пределах 200 км, которые возвращают данные, упорядоченные по некоторому пространственному порядку. Найти там записи, которые близки по времени, значит проверить каждую.
Или же вы находите записи по времени и получаете результаты по времени. Затем фильтрация этого списка по радиусу 200 км - это проверка каждого из них.
Если вы фильтруете данные в двух диапазонах, как это, становится трудно применить второй фильтр, используя индекс. Возможно, вам лучше запретить использовать пространственный индекс, если временной фильтр более узкий.
Если оба они велики по отдельности, и только вместе они тесно связаны, то у вас есть более сложная проблема, которую люди пытались решить в течение длительного времени, и которая могла бы быть хорошо решена с помощью индексов, охватывающих 3D (и далее) Космос. За исключением того, что у SQL Server их нет.
Сожалею.
Редактировать: подробнее ...
Эта проблема аналогична поиску диапазонов времени, охватывающих определенный момент времени. Когда вы ищете записи, которые начинаются до этого момента, у вас возникает неупорядоченный беспорядок времен окончания - и наоборот. Если вы ищете людей в телефонной книге, чьи фамилии начинаются с F, вы не можете надеяться найти людей, чьи имена начинаются с R, очень легко. И индекс по имени не помогает ни по той же причине. Найти вещи в следующем индексе сложно, когда ваш первый индекс не равен.
Теперь, если бы вы могли изменить свой фильтр даты на фильтр равенства (или серию фильтров равенства), у вас был бы шанс, за исключением того, что пространственный индекс является особым видом индекса и не может использоваться в качестве второго уровня в составной индекс.
Так что, боюсь, ты остался в неловкой ситуации. :(
Редактировать: Попробуйте:
Обратите внимание, что я намеренно нарушаю проходимость путем деления на 1000, прежде чем сравнивать с 200. Я хочу, чтобы эта работа была выполнена в поиске ключей.
Напоминаем, что вы могли бы избежать необходимости поиска (и подсказок), включив GeoPoint и Time в оба индекса ix_MJD. Это, безусловно, отнимает часть тепла в плане запросов.
источник
select top 10000 h.Time, m.Time, m.GeoPoint.STDistance(h.GeoPoint), h.mjd-m.mjd from L2V5.dbo.header h join L2.dbo.MLS_Header m on m.GeoPoint.STDistance(h.GeoPoint)<200000 and m.mjd between h.mjd-.125 and h.mjd+.125 order by h.mjd