2009-03-05 64 views
7

我会的任何意见,任何有关于感激:在varchar字段数据库中的VARCHAR字段,其存储的GPS位置

你怎么您有效地存储GPS(或浮点数),可索引


背景:

我们开发出能够有效地与元数据的集合一起存储任何类型的文件内容管理系统。此文件/元数据存储如下:

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 0.4343242,-1.32324' )内存储经度和纬度。

如何查询此字符串?有什么聪明的我可以用sql做什么,这将允许我查询字符串的“组件”?我可以将坐标存储为一个xml字符串 - 这会有帮助吗?这如何有效地索引?

2)在metadata_table中将经度和纬度存储为单独的行。

该解决方案解决了支持更容易查询的问题(以牺牲复杂性和不便性为代价,特别是当我将存储多个地理标签时),但是我仍然面临索引问题。

查询时,我可以将varchars转换为浮点数,但是我不确定这是否会忽略metadata_table.metadata_value上的索引,而是执行表扫描。

3)创建专门的浮点字段来存储GPS数据。

这是最不理想的选择,因为它违背了设计的粒度,为特定元数据添加数据库字段。并非所有文件都会存储GPS数据。

任何帮助或建议表示赞赏。

回答

1

对于选项1,我可以这样说:使用Gps eXchange Format (GPX)。这是保存GPS点的标准方式。可以选择标记航点,航迹和兴趣点。
但是,查询并不容易。

1

编辑:请参阅评论这个不足之处。

要回答您的基本问题,忽略背后的任何推理,您可以使用function-based indexes。如果你选择#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 
    ) 
    ) 
); 
+0

to_number(instr ...在metadata_value没有存储经度和纬度时会产生错误,请记住这个字段是以通用的方式使用的,所以它应该能够存储不同的数据,我认为它几乎是不可能在统一存储时对经度和纬度进行索引 – tuinstoel 2009-03-06 10:00:03

+0

好点也可能意味着仅仅执行索引的substr部分也是无效的也许只是创建经纬度数据和索引的实体化视图,选项 – Alkini 2009-03-06 14:44:34

2

使用专用浮点领域或类型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

一般来说,如果我有一个适合所有人的表(我不认为他们没有用),我倾向于允许一系列数据类型用于存储,并且在类型之前。例如。

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)你执行的是,在元数据表。

相关问题