Cải thiện truy vấn DbGeography


7

Tôi vẫn chưa quen với quản trị cơ sở dữ liệu và tôi đang cố gắng tối ưu hóa truy vấn tìm kiếm.

Tôi đã có một truy vấn giống như thế này và mất 5-15 giây để thực thi trong một số trường hợp và cũng gây ra việc sử dụng CPU 100%:

DECLARE @point geography;
SET @point = geography::STPointFromText('POINT(3.3109015 6.648294)', 4326); 

SELECT TOP (1)
     [Result].[PointId] AS [PointId], 
     [Result].[PointName] AS [PointName], 
     [Result].[LegendTypeId] AS [LegendTypeId], 
     [Result].[GeoPoint] AS [GeoPoint]
FROM ( 
    SELECT 
        [Extent1].[GeoPoint].STDistance(@point) AS distance, 
        [Extent1].[PointId] AS [PointId], 
        [Extent1].[PointName] AS [PointName], 
        [Extent1].[LegendTypeId] AS [LegendTypeId], 
        [Extent1].[GeoPoint] AS [GeoPoint]
    FROM [dbo].[GeographyPoint] AS [Extent1]
    WHERE 18 = [Extent1].[LegendTypeId] 
)  AS [Result]
ORDER By [Result].distance ASC

Bảng này có một chỉ mục được nhóm trên PK và một Chỉ mục không gian trên geographycột loại.

nhập mô tả hình ảnh ở đây

Vì vậy, khi tôi thực hiện truy vấn trên, nó đã thực hiện thao tác quét.

nhập mô tả hình ảnh ở đây

Vì vậy, tôi đã tạo một chỉ mục không được nhóm trên LegendTypeIdcột:

CREATE NONCLUSTERED INDEX [GeographyPoint_LegendType_NonClustered] ON [dbo].[GeographyPoint]
(
    [LegendTypeId] ASC
)
INCLUDE (   [PointId],
    [PointName],
    [GeoPoint]) 
    WITH (PAD_INDEX = OFF, 
    STATISTICS_NORECOMPUTE = OFF,
    SORT_IN_TEMPDB = OFF, 
    DROP_EXISTING = OFF,
    ONLINE = OFF,
    ALLOW_ROW_LOCKS = ON, 
    ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO

và thay đổi truy vấn thành:

DECLARE @point geography;
SET @point = geography::STPointFromText('POINT({0} {1})', 4326); 

 SELECT TOP (1) 
     [GeoPoint].STDistance(@point) AS distance, 
     [PointId], 
     [PointName],
     [LegendTypeId], 
     [GeoPoint]
     FROM [GeographyPoint]
 WHERE 18 = [LegendTypeId]
 ORDER By distance ASC

Và bây giờ SQL Server thực hiện tìm kiếm thay vì quét:

nhập mô tả hình ảnh ở đây

Theo quan điểm của tôi đã tăng hiệu quả của truy vấn, nhưng khi tôi triển khai nó vào sản xuất, tôi vẫn nhận được kết quả tương tự (sử dụng CPU cao và trung bình 10 giây để thực hiện truy vấn).

Lưu ý: Không có dữ liệu nào được chèn, cập nhật hoặc xóa khỏi bảng này - chỉ tìm kiếm / đọc.

  1. Có phải tôi đang làm gì sai không?

  2. Làm thế nào tôi có thể sửa lỗi này?

BIÊN TẬP

Chỉ số chi tiết

nhập mô tả hình ảnh ở đây

EDIT 2:

Tôi đã thay đổi truy vấn, để sử dụng phương thức: 'Hàng xóm gần nhất' từ liên kết: https://msdn.microsoft.com/en-us/l Library / ff929109.aspx và bây giờ đây là kết quả, Truy vấn này cũng đang mất 3 -5 giây cho tìm kiếm - tương tự như Truy vấn thứ hai, (nhưng không được thử nghiệm trên Sản xuất)

nhập mô tả hình ảnh ở đây

Cài đặt chỉ mục không gian:

CREATE SPATIAL INDEX [SPATIAL_Point] ON [dbo].[GeographyPoint]
(
[GeoPoint]
)USING  GEOGRAPHY_GRID 
WITH (GRIDS =(LEVEL_1 = MEDIUM,LEVEL_2 = MEDIUM,LEVEL_3 = MEDIUM,LEVEL_4 = MEDIUM), 
CELLS_PER_OBJECT = 16, PAD_INDEX = OFF, 
STATISTICS_NORECOMPUTE = 
OFF, SORT_IN_TEMPDB = OFF,
 DROP_EXISTING = OFF, 
 ONLINE = OFF, 
 ALLOW_ROW_LOCKS = ON, 
 ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO

EDIT 3 Tôi đã làm theo hướng dẫn của @MickyT, bỏ Index vào [LegendTypeId]và thực hiện truy vấn sau:

DECLARE @point geography;
SET @point = geography::STPointFromText('POINT(3.3109 6.6482)', 4326); 

SELECT TOP (1) 

    [PointId],
    [PointName],
    [LegendTypeId], 
    [GeoPoint]
FROM [GeographyPoint] WITH(INDEX(SPATIAL_Point))
WHERE 
   [GeoPoint].STDistance(@point) IS NOT NULL AND
    18 = [LegendTypeId]
ORDER By [GeoPoint].STDistance(@point) ASC
OPTION(MAXDOP 1)

Thống kê cho truy vấn này là

nhập mô tả hình ảnh ở đây

Và sau đó tôi thực hiện lại Truy vấn này:

DECLARE @point geography;
SET @point = geography::STPointFromText('POINT(3.3109 6.6482)', 4326); 

 SELECT TOP (1) 
     [GeoPoint].STDistance(@point) AS distance, 
     [PointId], 
     [PointName],
     [LegendTypeId], 
     [GeoPoint]
     FROM [GeographyPoint] --WITH(INDEX(SPATIAL_Point))
 WHERE 18 = [LegendTypeId]
 ORDER By distance ASC

Thống kê cho truy vấn này là

nhập mô tả hình ảnh ở đây


Có bao nhiêu hàng thực tế được trả về bởi tìm kiếm? Lưu ý rằng STDistance phải được tính cho mỗi hàng được trả về và toàn bộ kết quả được sắp xếp cho ORDER BY Distancemệnh đề.
Dan Guzman

@DanGuzman Tôi đã chỉnh sửa câu hỏi với chi tiết tìm kiếm
Dawood Awan

1
Truy vấn bạn đang xem được gọi là tìm kiếm hàng xóm gần nhất và khá phổ biến nhưng đắt tiền. Đây là trang MSDN mô tả các yêu cầu để thực hiện điều này một cách hiệu quả. Đây là từ năm 2012,
MickyT

@MickyT người hàng xóm gần nhất này dường như đang thực hiện giống như truy vấn thứ hai
Dawood Awan

Tôi hy vọng sẽ thấy nó đạt chỉ số không gian. Tôi sẽ có một cái nhìn tốt hơn vào buổi sáng. Bạn đang dùng phiên bản SQL Server nào và bạn có thể chia sẻ cài đặt cho chỉ mục không gian của mình không? Có bao nhiêu điểm trong bảng của bạn?
MickyT

Câu trả lời:


2

Tôi đã sử dụng các thiết lập sau để chạy một số thử nghiệm chống lại.

CREATE TABLE GeographyPoint (
    ID INTEGER IDENTITY(1,1) NOT NULL PRIMARY KEY,
    GeoPoint GEOGRAPHY NOT NULL,
    LegendTypeID INTEGER NOT NULL
    );

INSERT INTO GeographyPoint (GeoPoint, LegendTypeID)
SELECT TOP 1000000 
    Geography::Point(RAND(CAST(NEWID() AS VARBINARY(MAX))) * 2,RAND(CAST(NEWID() AS VARBINARY(MAX))) * 2,4326),
    CAST(RAND(CAST(NEWID() AS VARBINARY(MAX))) * 25 AS INTEGER)
FROM Tally;

CREATE INDEX GP_IDX1 ON GeographyPoint(LegendTypeID) INCLUDE (ID, GeoPoint);
CREATE SPATIAL INDEX GP_SIDX ON GeographyPoint(GeoPoint) USING GEOGRAPHY_AUTO_GRID;

Điều này mang lại cho bảng 1.000.000 điểm ngẫu nhiên với mức chênh lệch 2 x 2 độ.
Sau khi thử một vài tùy chọn khác nhau trên đó, hiệu suất tốt nhất tôi có thể nhận được là buộc nó sử dụng chỉ số không gian. Có một vài cách để đạt được điều này. Bỏ chỉ mục trên LegendTypeID hoặc sử dụng một gợi ý.
Bạn sẽ cần phải quyết định cái nào là tốt nhất cho tình huống của bạn. Cá nhân tôi không thích sử dụng gợi ý chỉ mục và sẽ bỏ chỉ mục khác nếu không cần thiết cho các truy vấn khác.

Các truy vấn xếp chồng lên nhau

DECLARE @point geography;
SET @point = geography::Point(1,1,4326); 
/*
Clustered index scan (PK)
 SQL Server Execution Times:
   CPU time = 641 ms,  elapsed time = 809 ms
*/
SELECT TOP (1) 
    [GeoPoint].STDistance(@point) AS distance, 
    [ID], 
    [LegendTypeId], 
    [GeoPoint]
FROM [GeographyPoint]
WHERE 18 = [LegendTypeId]
ORDER By distance ASC
OPTION(MAXDOP 1)
/*
Index Seek NonClustered (GP_IDX1)
 SQL Server Execution Times:
   CPU time = 2250 ms,  elapsed time = 2806 ms
*/
SELECT TOP (1) 
    [GeoPoint].STDistance(@point) AS distance, 
    [ID], 
    [LegendTypeId], 
    [GeoPoint]
FROM [GeographyPoint]
WHERE [GeoPoint].STDistance(@point) IS NOT NULL AND
    18 = [LegendTypeId]
ORDER By [GeoPoint].STDistance(@point) ASC
OPTION(MAXDOP 1)

/*
For the next 2 queries
Clustered Index Seek (Spatial)
 SQL Server Execution Times:
   CPU time = 15 ms,  elapsed time = 11 ms
*/
SELECT TOP (1) 
    [GeoPoint].STDistance(@point) AS distance, 
    [ID], 
    [LegendTypeId], 
    [GeoPoint]
FROM [GeographyPoint] WITH(INDEX(GP_SIDX))
WHERE [GeoPoint].STDistance(@point) IS NOT NULL AND
    18 = [LegendTypeId]
ORDER By [GeoPoint].STDistance(@point) ASC
OPTION(MAXDOP 1)

DROP INDEX GP_IDX1 ON [GeographyPoint]

SELECT TOP (1) 
    [GeoPoint].STDistance(@point) AS distance, 
    [ID], 
    [LegendTypeId], 
    [GeoPoint]
FROM [GeographyPoint]
WHERE [GeoPoint].STDistance(@point) IS NOT NULL AND
    18 = [LegendTypeId]
ORDER By [GeoPoint].STDistance(@point) ASC
OPTION(MAXDOP 1)

Tôi có nên xóa chỉ mục Clustered trên PK trong bảng của mình không?
Dawood Awan

@DawoodAwan Đừng xóa chỉ mục được nhóm của bạn, nó là bắt buộc cho chỉ mục không gian. Cái khiến trình tối ưu hóa loại bỏ bằng cách sử dụng chỉ mục không gian là chỉ mục không được nhóm trên LegendTypeID
MickyT

Ok, tôi đang dùng thử, các cài đặt trên Chỉ số không gian của tôi có ổn không?
Dawood Awan

@DawoodAwan Họ trông ổn đối với tôi, nhưng nó thực sự phụ thuộc vào dữ liệu trong bảng. Vì đó là điểm nên không có nhiều điều chỉnh có thể được thực hiện.
MickyT

Tôi đã kiểm tra các đề xuất bạn đã đưa ra - và tôi đã thêm kết quả vào câu hỏi trong Chỉnh sửa 3, số lần đọc logic đã tăng từ 452 lên 4523, đây có phải là một dấu hiệu tốt không?
Dawood Awan
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.