Хранение местоположений GPS в поле базы данных varchar - PullRequest
7 голосов
/ 05 марта 2009

Буду благодарен за любые советы, которые кто-либо имеет в отношении:

Как вы эффективно храните gps (или любое число с плавающей запятой) в поле varchar, которое может быть проиндексировано .


Справочная информация:

Мы разрабатываем систему управления контентом, которая может эффективно хранить файлы любого типа вместе с набором метаданных. Этот файл / метаданные хранятся следующим образом:

file_table              metadata_table
----------              --------------
file_id         ->      file_id (number)
file_name               metadata_id (number)
file_location           metadata_value (varchar)
...etc

Меня попросили обеспечить поддержку файлов геотегирования (т. Е. Хранить координаты GPS в виде метаданных). Кроме того, мы также хотели бы поддерживать файлы с несколькими геотегами.

Теперь, насколько я вижу, у меня есть несколько вариантов:

1) Сохранение широты и долготы в пределах одного и того же metadata_value varchar (например, '52 .4343242, -1.32324 ').

Как бы я запросил эту строку? Есть ли что-нибудь умное, что я могу сделать с sql, что позволит мне запрашивать «компоненты» строки? Могу ли я сохранить координаты в виде строки XML - это поможет? Как это можно эффективно проиндексировать?

2) Сохранить широту и долготу в виде отдельных строк в metadata_table .

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

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

3) Создание выделенных полей с плавающей запятой для хранения данных GPS.

Это наименее желательный вариант, поскольку он идет вразрез с дизайном, добавляя поля базы данных для определенных метаданных. Не все файлы будут хранить данные GPS.

Любая помощь или совет приветствуется.

Ответы [ 7 ]

4 голосов
/ 05 марта 2009

Вы можете использовать локатор Oracle. Свободное подмножество Oracle Spatial для выполнения всех видов различных географических манипуляций и индексации пространственных данных: http://www.oracle.com/technology/products/spatial/index.html

С помощью типа столбца mdsys.sdo_geometry вы можете хранить точки, облака точек, линии, многоугольники и трехмерные объекты в базе данных.

3 голосов
/ 05 марта 2009

Хотя вы пометили это с Oracle, я подумал, что это будет полезно для всех, кто использует MySQL: используйте пространственные расширения для хранения данных о местоположении .

3 голосов
/ 05 марта 2009

Может ли это быть какая-то помощь: http://postgis.refractions.net

2 голосов
/ 06 марта 2009

Использование выделенных полей с плавающей точкой или столбцов типа mdsys.sdo_geometry - лучший способ сохранить эти данные. Если файл не содержит данных GPS, эти поля будут пустыми, но почему это должно быть проблемой? Если файл может иметь более одной связанной точки, используйте подробную таблицу.

Опции 1 и 2 являются «общим» решением. Общие решения для баз данных работают медленно, потому что их труднее индексировать, а сбор статистики усложняется, поэтому оптимизатору запросов становится все труднее.

Кроме того, для ваших пользователей сложнее составить отчетность по сбору управленческой информации с помощью таких инструментов, как Cognos (бизнес-аналитика), с помощью общего решения.

Сохранение дат в поле даты, чисел в поле чисел и географической информации в географическом поле (mdsys.sdo_geometry).

Здесь объясняется, почему сохранение даты, такой как '20031603' в числовом поле, замедляет процесс: http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:77598210939534.

1 голос
/ 06 марта 2009

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

CREATE TABLE MetaDataType (
  MetaDataID int IDENTITY(1,1) not null,
  MetaDataType varchar(10) not null,
  constraint PK_MetaDataType PRIMARY KEY (MetaDataID),
  constraint UQ_MetaDataType_TypeCheck UNIQUE (MetaDataID,MetaDataType),
  constraint CK_MetaDataType CHECK (MetaDataType in ('INT','CHAR','FLOAT'))
)

И тогда таблица метаданных будет выглядеть так:

CREATE TABLE MetaData (
  FileID int not null,
  MetaDataID int not null,
  MetaDataType varchar(10) not null,
  IntValue int null,
  CharValue varchar(max) null,
  FloatValue float null,
  constraint PK_MetaData PRIMARY KEY (FileID,MetaDataID),
  constraint FK_MetaData_Files FORIEGN KEY (FileID) references /* File table */,
  constraint FK_MetaData_Types FOREIGN KEY (MetaDataID,MetaDataType) references MetaDataTypes (MetaDataID,MetaDataType),
  constraint CK_MetaData_ValidTypes ((MetaDataType = 'INT' or IntValue is null) and (MetaDataType = 'CHAR' or CharValue is null) and (MetaDataType = 'FLOAT' or FloatValue is null))
)

Суть в том, что 1) вы сохраняете для каждого элемента метаданных ожидаемый тип и 2) применяете это в таблице метаданных.

1 голос
/ 05 марта 2009

РЕДАКТИРОВАТЬ: см. Комментарии, где это не хватает.

Чтобы ответить на ваш базовый вопрос, не обращая внимания ни на одну из причин, стоящих за ним, вы можете использовать функционально-ориентированные индексы . Если вы выберете вариант № 2, это должно быть просто.

Если вы придерживаетесь # 1, вам просто нужно добавить несколько instr / substr voodoo; например:

select 
    to_number(
      substr(
          '52.4343242,-1.32324'
        , 1
        , instr( '52.4343242,-1.32324', ',' ) - 1
      )
    ) as lattitude
  , to_number(
      substr(
          '52.4343242,-1.32324'
        , instr( '52.4343242,-1.32324', ',' ) + 1
      )
    ) as longitude
from dual;

Итак, вы бы сделали что-то вроде:

create index lat_long_idx on metadata_table ( 
    to_number(
      substr(
          metadata_value
        , 1
        , instr( metadata_value, ',' ) - 1
      )
    )
  , to_number(
      substr(
          metadata_value
        , instr( metadata_value, ',' ) + 1
      )
    )
);
1 голос
/ 05 марта 2009

Для варианта 1 я могу сказать: Используйте Формат обмена Gps (GPX) . Это стандартный способ сохранения точек GPS. Есть варианты для отметки путевых точек, треков и точек интереса.
Тем не менее, запрос не так просто.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...