У меня с трудом удается решить следующую проблему.
У меня есть матрица 15000x15000
xy. Я сохраняю расположение элементов в этой матрице, определяя координату x, y для элемента. Я хочу отобразить часть матрицы в так называемом окне просмотра. Размеры видового экрана являются, например, 1600x1000
Рассмотрим следующую структуру db:
Element (element_id, image, width, height)
Globe_Element (ge_id, x, y, element_id)
При единственном input
, являющемся ax, координата y в сетке (500x500), как я могу выбрать все строки Globe_Element
, которые видны в области просмотра (6x4)?
Пример окна просмотра http://img33.imageshack.us/img33/6089/viewportexample.jpg
Вышеприведенное изображение демонстрирует проблемы. Маленькие оранжевые квадраты - это элементы, которые должны быть включены, маленькие красные квадраты не должны (смотря на ближайший видовой экран). Большие цветные блоки (синий, желтый, зеленый и красный (опять же, извините за путаницу) являются видовыми экранами. Один цвет - один видовой экран. Серые круги определяют входные координаты.
Для эффективного использования в SQL я бы рекомендовал вам выбрать СУБД с пространственной поддержкой (часто под названием поддержка GIS) или с поддержкой двух- или многомерных индексов (я их не знаю).
Я думаю, что только тогда вы сможете сделать так, чтобы ваши запросы использовали индексы для эффективной работы.
Postgres имеет пространственную поддержку (под названием PostGIS), как и MS SQL 2008 и Oracle. Я использовал только MS SQL 2008 для пространственных, вот хороший обзор того, как его пространственный индекс подразделяет поверхность.
Без многомерных индексов у вас будут свои объекты на диске, упорядоченные вдоль одной координатной оси, следовательно, вы сможете ограничить сканирование таблиц только по одной оси координат.
Если вы хотите остаться с MySQL (ответьте на комментарий OP ниже):
Я думаю, что лучше создать запрос с конкретными значениями - независимо от того, выполняете ли вы это на PHP или в хранимой процедуре на стороне SQL, - это другой вопрос. Но это просто и достаточно легко сделать в PHP, поэтому я рекомендовал бы это.
Вы можете принимать такие решения, как то, что видовое окно находится в позиции без паузы (синий на диаграмме выше), а затем достаточно, чтобы испускать один запрос с простым предложением WHERE xmin>=viewport_xmin AND xmax<=viewport_xmax AND ymin>=viewport_ymin AND ymax<=viewport_ymax
. Или посмотрите, что видовой порт обертывает, а затем экспериментирует, будет ли быстрее выполнять 2/4 отдельных простых запроса для каждой из 2/4 разворачивающихся частей портала или поставить все 2/4 простые запросы с помощью OR
между ними в одном большом запросе. Вам нужно будет увидеть, какой из них будет быстрее, экспериментировать с индексами, посмотреть планы запросов и т.д.
Предполагая, что ваш координатный параметр - верхний левый угол окна просмотра, что-то вроде этого, как правило, выбрать соответствующие строки:
выберите * из globe_element g, элемент e
где
e.element_id = g.element_id и
((x < ширина и x между @x_param и (@x_param + 6)) или (x > -1 и x между (@x_param - width) и (@x_param - width + 6)))
и
((y_loc < height и y_loc между @y_param и (@y_param + 4)) или (y_loc > -1 и y_loc между (@y_param - высота) и (@y_param - высота + 4)))
Это просто общий sql, а не mysql specific (по крайней мере, параметры).
В общем: выберите, где x находится между x_param и x_param + view_port_width, а y находится между y_param и y + param + view_port_height. Если вычисленная координата больше, чем view_port_width/height, вычтите 500, чтобы получить соответствующее завернутое местоположение.
Это не упорядочивает координаты каким-либо образом.
Кроме того, ваша "Сферическая" среда на самом деле не выглядит сферической... как вы привязываете сетку к сфере? Точно так же, как градусы lat/long на земле, где площадь каждой квадратной единицы сжимается, когда вы добираетесь до полюсов? Если это произойдет, то это сработает. Если нет, то то, что я написал, - это мусор. Однако, если это так, то решение этого в SQL тоже.... неверно.