Câu hỏi:
Tôi có một bảng không gian (đường kẻ), được lưu trữ bằng SDE.ST_GEOMETRY
kiểu dữ liệu do người dùng định nghĩa của ESRI trong cơ sở dữ liệu địa lý Oracle 12c . Tôi muốn liệt kê các đỉnh dòng để cuối cùng tôi có thể truy cập và cập nhật tọa độ của chúng. Nếu tôi đang sử dụng SDO_GEOMETRY / Oracle Locator, thì tôi sẽ sử dụng
SDO_UTIL.GETVERTICES
chức năng này. Nhưng tôi không sử dụng SDO_GEOMETRY / Oracle Locator và không có chức năng tương đương SDE.ST_GEOMETRY
. Các SDE.ST_GEOMETRY
hàm duy nhất tôi có thể tìm thấy liên quan đến các đỉnh là ST_PointN
và ST_NumPoints
.
Tôi đã đưa ra một truy vấn thực hiện thành công tất cả những điều này - lấy các đỉnh của dòng là các hàng (lấy cảm hứng từ trang này ):
1 SELECT a.ROAD_ID
2 ,b.NUMBERS VERTEX_INDEX
3 ,a.SDE.ST_X(SDE.ST_PointN(a.SHAPE, b.NUMBERS)) AS X
4 ,a.SDE.ST_Y(SDE.ST_PointN(a.SHAPE, b.NUMBERS)) AS Y
5 FROM ENG.ROADS a
6 CROSS JOIN ENG.NUMBERS b
7 WHERE b.NUMBERS <= SDE.ST_NumPoints(a.SHAPE)
8 --removed to do explain plan: ORDER BY ROAD_ID, b.NUMBERS
----------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time |
----------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 5996 | 1545K| | 262 (1)| 00:00:01 |
| 1 | MERGE JOIN | | 5996 | 1545K| | 262 (1)| 00:00:01 |
| 2 | INDEX FULL SCAN | R23715_SDE_ROWID_UK | 30 | 90 | | 1 (0)| 00:00:01 |
|* 3 | SORT JOIN | | 3997 | 1018K| 2392K| 261 (1)| 00:00:01 |
| 4 | TABLE ACCESS FULL| ROAD | 3997 | 1018K| | 34 (0)| 00:00:01 |
----------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
" 3 - access(""B"".""NUMBERS""<=""SDE"".""ST_NumPoints""(""A"".""SHAPE""))"
" filter(""B"".""NUMBERS""<=""SDE"".""ST_NumPoints""(""A"".""SHAPE""))"
Nó CROSS JOINS
là các dòng trong ROADS
bảng thành một NUMBERS
bảng (và giới hạn kết quả với số lượng đỉnh trong mỗi dòng).
Số liệu thống kê: (cập nhật)
- Mỗi dòng có tối đa 30 đỉnh (trung bình 4,38 đỉnh trên mỗi dòng)
- ROADS có 3.997 dòng
- NUMBERS có 30 hàng (số liên tiếp bắt đầu từ 1)
- Tập kết quả có 17.536 hàng
Tuy nhiên, hiệu suất kém (40 giây) và tôi không thể không nghĩ - có cách nào thanh lịch hơn để làm điều này không? Đối với tôi, sử dụng bảng số và nối chéo có vẻ như là một cách tiếp cận cẩu thả. Có cách nào tốt hơn?
Điều khoản của Layman sẽ được đánh giá cao; Tôi là một chàng trai của Công trình Công cộng, không phải là một DBA.
Cập nhật số 1:
Nếu tôi xóa các dòng 3 & 4 (chuỗi các hàm liên quan đến X & Y) khỏi truy vấn, nó sẽ thực thi ngay lập tức. Nhưng tất nhiên, tôi không thể xóa những dòng này, tôi cần các cột X & Y. Vì vậy, điều này khiến tôi tin rằng hiệu suất chậm có liên quan đến các chức năng X & Y.
Tuy nhiên, nếu tôi xuất các điểm sang một bảng tĩnh, rồi chạy các hàm X & Y trên đó, thì điều này cũng thực thi ngay lập tức.
Vì vậy, điều này có nghĩa là hiệu suất chậm được gây ra bởi các chức năng X & Y, ngoại trừ, không, không phải vậy sao? Tôi bối rối.
Cập nhật số 2:
Nếu tôi mang X và Y ra khỏi truy vấn, hãy đặt chúng vào một truy vấn bên ngoài và thêm ROWNUM vào truy vấn bên trong, thì nó sẽ nhanh hơn nhiều (16 giây - được cập nhật):
SELECT
ROWNUM
,ROAD_ID
,VERTEX_INDEX
,SDE.ST_X(ST_POINT) AS X
,SDE.ST_Y(ST_POINT) AS Y
FROM
(
SELECT
ROWNUM
,a.ROAD_ID
,b.NUMBERS VERTEX_INDEX
,SDE.ST_PointN(a.SHAPE, b.NUMBERS) AS ST_POINT
FROM ENG.ROAD a
CROSS JOIN ENG.NUMBERS b
WHERE b.NUMBERS <= SDE.ST_NumPoints(a.SHAPE)
)
--removed to do explain plan: ORDER BY ROAD_ID, VERTEX_INDEX
-------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time |
-------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 5996 | 322K| | 262 (1)| 00:00:01 |
| 1 | COUNT | | | | | | |
| 2 | VIEW | | 5996 | 322K| | 262 (1)| 00:00:01 |
| 3 | COUNT | | | | | | |
| 4 | MERGE JOIN | | 5996 | 1545K| | 262 (1)| 00:00:01 |
| 5 | INDEX FULL SCAN | R23715_SDE_ROWID_UK | 30 | 90 | | 1 (0)| 00:00:01 |
|* 6 | SORT JOIN | | 3997 | 1018K| 2392K| 261 (1)| 00:00:01 |
| 7 | TABLE ACCESS FULL| ROAD | 3997 | 1018K| | 34 (0)| 00:00:01 |
-------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
" 6 - access(""B"".""NUMBERS""<=""SDE"".""ST_NumPoints""(""A"".""SHAPE""))"
" filter(""B"".""NUMBERS""<=""SDE"".""ST_NumPoints""(""A"".""SHAPE""))"
Justin Cave giải thích tại sao ROWNUM giúp hiệu suất ở đây: Tại sao việc thêm ROWNUM vào truy vấn sẽ cải thiện hiệu suất?
Mặc dù cải thiện hiệu suất này là tốt, nhưng nó vẫn chưa đủ tốt. Và tôi không thể không nghĩ rằng tôi vẫn không hiểu đầy đủ về cách thức truy vấn hoạt động hoặc tại sao nó lại chậm như vậy.
Câu hỏi vẫn còn: có cách nào tốt hơn không?