Cách thiết lập giải pháp cho tìm kiếm khoảng cách đa chiều với các loại dữ liệu không gian của SQL Server


7

Tôi có một giải pháp cơ sở dữ liệu hiện có không hoạt động tốt. Tôi đang tìm kiếm dữ liệu đa chiều với cấu trúc bảng truyền thống bằng cách sử dụng float, v.v ... Cơ sở dữ liệu chứa ~ 1-2M hàng.

Sau một số tìm kiếm, tôi đã tìm thấy các loại dữ liệu không gian của SQL Server nơi bạn có thể xác định hình học dựa trên Điểm hoặc MultiPoint nơi bạn có thể tìm kiếm với khoảng cách. Tôi nghĩ rằng đây có thể là một giải pháp nhưng tôi cần sự giúp đỡ để bắt đầu đi đúng hướng.

Cấu trúc bảng hiện tại của tôi như sau khi mỗi hàng chứa 2 (cuối cùng nhiều hơn) các giá trị XYZ:

    | ID | X1  | Y1  | Z1  | X2  | Y2  | Z2  |
    | 1  | 1.1 | 2.2 | 5.1 | 1.2 | 2.1 | 4.1 |
    | 2  | 3.2 | 5.1 | 4.1 | 3.2 | 3.1 | 3.1 |
    | 3  | 4.1 | 2.3 | 6.3 | 4.2 | 4.1 | 2.1 |
    | 4  | 2.4 | 3.5 | 2.1 | 3.2 | 2.1 | 4.1 |

Tôi đang thực hiện tìm kiếm với dung sai cho từng giá trị X, Y và Z.

Ví dụ:

    (pseudocode)
    declare targetXYZ1 = (4.1, 2.2, 3.1);
    declare targetXYZ2 = (2.8, 2.2, 4.2);

    declare toleranceXYZ = (2,2,2)

    Select ID from MyXYZTable tb
    Where 
           Math.Abs(tb.X1 - targetXYZ1.X1) < toleranceXYZ.X 
       AND Math.Abs(tb.Y1 - targetXYZ1.Y1) < toleranceXYZ.Y
       AND Math.Abs(tb.Z1 - targetXYZ1.Z1) < toleranceXYZ.Z

       AND Math.Abs(tb.X2 - targetXYZ1.X2) < toleranceXYZ.X 
       AND Math.Abs(tb.Y2 - targetXYZ1.Y2) < toleranceXYZ.Y
       AND Math.Abs(tb.Z2 - targetXYZ1.Z2) < toleranceXYZ.Z

Sau một số phân tích, có lẽ tôi sẽ cần tạo một bảng có 1 hoặc 2 cột hình học cho xyz1 và xyz2 với hình học :: Point (0, 0, 0)

Những câu hỏi của tôi:

  1. Có một giải pháp khả thi với các loại không gian SQL Server không?
  2. Tôi có cần sử dụng tìm kiếm hàng xóm gần nhất không hoặc tôi có thể sử dụng STDistance
  3. Tôi có cần thiết lập một chỉ mục không gian cho bảng không?

Bất kỳ lời khuyên hoặc lời khuyên và thủ thuật đều rất hoan nghênh!

Câu trả lời:


5

Có thể có một số phương pháp không gian hữu ích ở một mức độ nào đó, nhưng vấn đề lớn nhất của bạn sẽ là giá trị Z :

Các tọa độ Z không được sử dụng trong bất kỳ tính toán nào được thực hiện bởi thư viện và không được thực hiện thông qua bất kỳ tính toán nào của thư viện.

Đây là do thiết kế. Đừng nghĩ các đối tượng không gian SQL là các đối tượng hình học 3D "thật", hãy nghĩ về chúng như các tọa độ bản đồ với "thẻ độ cao" không được đưa vào bất kỳ tính toán nào. Vì vậy, chức năng khoảng cách hoạt STDistance()động tuyệt vời cho "khoảng cách bản đồ", nhưng không phải là khoảng cách 3D thực sự.

Bạn có thể xác định giá trị Z (và giá trị "M") của một điểm, nhưng nó không được sử dụng bởi bất kỳ phép tính nào.

Để lam sang tỏ:

DECLARE @a geometry = geometry::Parse('POINT(0 0 0 2)');
DECLARE @b geometry = geometry::Parse('POINT(1 0 5 1)');
SELECT @a.Z, @b.Z, @a.STDistance(@b)

sẽ trả về các giá trị

0   5   1

Rõ ràng khoảng cách giữa hai điểm này phải lớn hơn 1, nếu nó sử dụng Z đúng cách. Vì vậy, họ có thể không làm việc như bạn hy vọng.

Nhưng nếu bạn ổn với việc bỏ qua giá trị Z, thì việc thực hiện các tính toán này sẽ khá đơn giản. Bạn có thể đọc các giá trị này từ bảng hiện có của mình như vậy:

SELECT geometry::Point(X1,Y1,0).STDistance(geometry::Point(X2,Y2,0))
From myTable;  

(Việc 0sử dụng này không phải là giá trị Z, đó là SRID .)

hoặc, nếu bạn dành thời gian để thay đổi cách chúng thực sự được lưu trữ:

CREATE TABLE myPoints (ID INT, P1 geometry, P2 geometry)

INSERT myPoints 
SELECT 1, geometry::Point(X1, Y1, 0), geometry::Point(X2, Y2, 0)
FROM oldTable

SELECT ID, P1.STDistance(P2)
FROM myPoints

Có một số thảo luận liên quan trong một trong những câu trả lời cũ của tôi ở đây .

EDIT : Một số suy nghĩ thêm:

  1. Về hiệu suất, tôi hoàn toàn không có manh mối về cách geometrycác đối tượng sẽ so sánh, hiệu suất khôn ngoan, với bạn làm toán bằng tay. Tôi tưởng tượng việc chuyển đổi sang các đối tượng Hình học một cách nhanh chóng sẽ có một mức phí nhất định, nhưng có lẽ chuyển đổi cách lưu trữ dữ liệu thô của bạn sẽ làm tốt hơn. Kiểm tra sẽ là chìa khóa ở đây.
  2. Các tham số Z có thể không được sử dụng bởi các STDistance()chức năng, nhưng rõ ràng bạn có thể tự truy vấn Z , và sử dụng nó để làm điều đó một phần của toán học cho mình, chỉ cần sử dụng Pythagoras: True3D_Distance ^ 2 = STDistance ^ 2 + (AZ-BZ) ^ 2
  3. Nhưng lưu ý rằng nếu mục tiêu của bạn chỉ đơn giản là xếp hạng các điểm theo mức độ gần gũi và bạn không cần tính khoảng cách thực tế , bạn có thể đơn giản hóa việc tính toán của mình. Tôi đang suy nghĩ một cái gì đó như WHERE PointA.STDistance(PointB) + ABS(PointA.Z-PointB.Z) < tolerancehoặc có lẽWHERE PointA.STDistance(PointB) < tolerance AND ABS(PointA.Z-PointB.Z) < tolerance

Cảm ơn bạn đã làm rõ, điều này giúp tôi tiết kiệm rất nhiều thời gian điều tra công nghệ này trong SQL. Có lẽ tôi sẽ phải gắn bó với cách tiếp cận nhiều cột (float) :-) và đặt một số chỉ mục thông minh vào nó để làm cho nó nhanh hơn. Cảm ơn!
wilkokosten

Không có vấn đề gì, @wilkokosten, rất vui vì tôi có thể giúp đỡ. Tôi đã thêm một vài suy nghĩ vào bài viết của mình; rõ ràng nó không phải là tất cả hoặc không có gì, bạn có thể hình dung sử dụng các hàm không gian cho một số phần và tính toán thủ công cho các phần khác. Chúc may mắn.
BradC

0

Là một lưu ý phụ, PostGIS hỗ trợ các chuỗi 3d và SRID (mà SQL Server không có). Xem ST_3DDistance . Và nó sẽ thực hiện KNN trên một chỉ mục 3d bằng cách sử dụng <<->>toán tử và ST_3DDWithin

SELECT *
FROM tbl_Foo AS t
WHERE ST_3DDWithin( t.3dgeom, mycord, distance_in_meters );
  ORDER BY t.3dgeom <<->> mycord;

^ Tìm và đặt nó trên một chỉ mục.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.