2009-03-05 29 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)你執行的是,在元數據表。

相關問題