2016-04-14 8 views
0

私たちは、顧客のサブセットのそれぞれに最も近い顧客を取得しようとしています。私たちのSQLは期待通りに動作しますが、小規模なテストデータベース(4,000人の顧客、50個のサブセット)でも数秒かかりますが、明らかにデータベースサイズが大きくなるにつれて劇的に増加します。SQLで距離計算を改善する方法

select ... custA data, custB data 
from customers custA 
left join customers custB on custB.id= 
    (select custC.id 
     from customers custC 
     where custC.id<>custA.id 
     order by distance(custA.lat,custA.lon,custC.lat,custC.lon) asc limit 1) 
where ... custA conditions 

距離それが示唆:)

を確認するために名前だ、まさに計算する関数である、我々は同じ状態または類似の顧客のみを比較するので、フィルタのいくつかの種類を検索する...または置くことができますlatやlonのdiferenceの最大値などですが、SQL構造を改善する方法はありますか?

Thks

答えて

0

私はあなたの問題を提案しています。 Customersテーブルを模倣するためにテーブル変数を使用していて、ダミーデータでいっぱいです。簡単にするために、私は距離関数の使用法を削除しましたが、あなたの環境で簡単に置き換えることができます。

私は1

私のソリューションは、SQL Server用に書かれているTOPにあなたの内側のクエリを置き換えるためにROW_NUMBERを利用しています:

create table customers (
    id int identity(1,1), 
    distance int 
) 
go 


insert into customers values(10) 
insert into customers values(100) 
insert into customers values(20) 
insert into customers values(30) 
insert into customers values(40) 
insert into customers values(50) 
insert into customers values(60) 
go 

create view AllCustomerDistances with SCHEMABINDING 
as 
select custA.Id custA_Id, custC.Id custC_id, custA.distance - custC.distance [distanceBetweenAandC] --distance(custA.lat, custA.lon, custC.lon, custC.lon) [distanceBetweenAandC] 
from 
    dbo.customers custA cross join 
    dbo.customers custC 
where 
    custA.Id <> custC.Id 

go 

select * 
from 
( select 
     custA.Id [A], 
     custB.Id [B], 
     row_number() over (partition by custA_Id order by distanceBetweenAandC desc) as Rownumber 
    from 
    AllCustomerDistances d inner join 
     customers custA on (d.custA_Id = custA.Id) inner join 
     customers custb on (d.custC_Id = custb.Id) 
) r 
where 
    Rownumber = 1 

私のサブクエリは、すべての顧客とROW_NUMBER間の距離を算出し、私は距離で注文し、小さな組み合わせだけを選択することができます。

EDIT:距離を計算してSQL Serverに格納するビューを使用しています。 WITH SCHEMABINDINGオプションを使用すると、SQL Serverはビューを前処理できるので、ビューを複数回呼び出すとクエリが大幅に高速になります。この影響は、初めてクエリを実行したときに発生します。参照されたレコードが変更されると、ビューに自動的に更新が表示されます。

+0

興味深い考えをありがとうが、初期の構文が改善されるわけではありません。私たちはそれをテストし、オリジナルの1.6倍から1.8倍の間を要します。一致する顧客のサブセットとして、関係は悪化します。 – DeepButi

+0

私は私の答えを編集し、今はインデックス付きのビューを使用しています。私はこれがあなたのケースで使用できるのかどうかはわかりませんが、クエリーを実行するたびに顧客間の距離を計算するのにかかる時間はクエリを殺している可能性があります。索引付きビューでは、ビューが初めてマテリアライズされるときに発生します。 –

+0

提案していただきありがとうございます。私たちはPostgressデータベースを使用しています。最も類似した概念はMATERIALIZEDビューです。マテリアライズド・ビューは、ソース表があるときにビュー・データが更新されないため、定期的なプロセスで明示的に再構築する必要があります。何千ものレコード(すべての顧客テーブルとのクロス・ジョイン)が含まれているため、本番システムで全体のビューを構築するために必要な時間はわかりません...試してみましょう。 – DeepButi