2011-12-15 10 views
1

郵便番号、住所などの巨大なデータベース(約500,000)があります。私は100マイルからの昇順でそれらを表示する必要がありますユーザーの郵便番号です。私は関連する緯度と経度の郵便番号のテーブルを持っています。どのような高速/より良い解決策になりますか?巨大なSQL Serverデータベースを使った距離計算

ケース1:距離を計算し、距離で並べ替える。私はセッション中にユーザーに現在の郵便番号、緯度、経度を持たせます。私はSQL Server関数を使って距離を計算します。

ケース2:50マイル圏内のすべての郵便番号を取得し、すべての郵便番号でビジネスを取得する。ここでは、ビジネスを見つけながらネストされたクエリでselectを書く必要があります。

ケース1は、データベース内のすべてのビジネスの距離を計算すると考えています。 2番目のケースでは郵便番号だけが取得され、必要なビジネスのみを取得します。したがって、ケース2はより良いはずですか?私はここで何か提案を感謝します。ここで

ケースサイドノートアプリ1.

var businessListQuery = (from b in _DB.Businesses 
         let distance = _DB.CalculateDistance(b.Zipcode,userLattitude,userLogntitude) 
         where b.BusinessCategories.Any(bc => bc.SubCategoryId == subCategoryId) 
             && distance < 100 
         orderby distance 
         select new BusinessDetails(b, distance.ToString())); 

int totalRecords = businessListQuery.Count(); 
var ret = businessListQuery.ToList().Skip(startRow).Take(pageSize).ToList(); 

のため、私が持っているLINQクエリは、C#であるされています。

おかげ

+2

SQLを記述し、実行計画と統計を実行し、より速いものを見てください。パフォーマンスに問題がある場合は、ストアドプロシージャを作成してデータベースに格納し、比較してください。 –

+0

インデックスビューを作成してインデックスにZipcodeを使用すると、このようにしてより速い結果を得ることができます。また、検索および注文時にインデックスベースを変更することもできます。 – KuldipMCA

+0

シンプルで非常に高速な方法http://stackoverflow.com/questions/3983325/calculate-distance-between-zip-codes-and-users/3989830#3989830 –

答えて

4

あなたは、たとえば、GEOGRAPHYデータ型を見てより悪い行うことができます:

CREATE TABLE Places 
(
    SeqID  INT IDENTITY(1,1), 
    Place  NVARCHAR(20), 
    Location GEOGRAPHY 
) 
GO 
INSERT INTO Places (Place, Location) VALUES ('Coventry', geography::Point(52.4167, -1.55, 4326)) 
INSERT INTO Places (Place, Location) VALUES ('Sheffield', geography::Point(53.3667, -1.5, 4326)) 
INSERT INTO Places (Place, Location) VALUES ('Penzance', geography::Point(50.1214, -5.5347, 4326)) 
INSERT INTO Places (Place, Location) VALUES ('Brentwood', geography::Point(52.6208, 0.3033, 4326)) 
INSERT INTO Places (Place, Location) VALUES ('Inverness', geography::Point(57.4760, -4.2254, 4326)) 
GO 
SELECT p1.Place, p2.place, p1.location.STDistance(p2.location)/1000 AS DistanceInKilometres 
    FROM Places p1 
    CROSS JOIN Places p2 
GO 
SELECT p1.Place, p2.place, p1.location.STDistance(p2.location)/1000 AS DistanceInKilometres 
    FROM Places p1 
     INNER JOIN Places p2 ON p1.SeqID > p2.SeqID 
GO 

geography::Pointは、緯度と経度だけでなく、SRID(とくにID番号)を取ります。この場合、SRIDは標準の緯度と経度である4326です。あなたはすでに緯度と経度を持っているので、ALTER TABLE地理学の列を追加してUPDATEを追加するだけです。

私はテーブルからデータを取り出す2つの方法を示しましたが、これでインデックス付きビューを作成することはできません(インデックス付きビューは自己結合できません)。あなたは効果的にキャッシュであるセカンダリテーブルを作成することはできますが、それは上記に基づいて作成されます。あなたはそれを維持することについて心配する必要があります(トリガーや他のプロセスを通して行うことができます)。

クロス結合により250,000,000,000行が得られますが、場所の列の1つを見るだけで検索は簡単です(つまり、SELECT * FROM table WHERE Place1 = 'Sheffield' AND distance < 100、2番目の行はかなり少ない行になりますが、 Place1列とPlace2列の両方を考慮してください)。