Pertanyaan:
Saya memiliki tabel spasial (garis jalan), disimpan menggunakan SDE.ST_GEOMETRY
tipe data ESRI yang ditentukan pengguna dalam geodatabase Oracle 12c . Saya ingin membuat daftar garis simpul sehingga saya akhirnya dapat mengakses & memperbarui koordinat mereka. Jika saya menggunakan SDO_GEOMETRY / Oracle Locator, maka saya akan menggunakan
SDO_UTIL.GETVERTICES
fungsinya. Tapi saya tidak menggunakan SDO_GEOMETRY / Oracle Locator, dan tidak ada fungsi yang setara di SDE.ST_GEOMETRY
. Satu-satunya SDE.ST_GEOMETRY
fungsi yang saya temukan yang berhubungan dengan simpul adalah ST_PointN
dan ST_NumPoints
.
Saya telah datang dengan kueri yang berhasil melakukan semua ini - dapatkan simpul garis sebagai baris (terinspirasi oleh halaman ini ):
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""))"
Ini CROSS JOINS
garis dalam ROADS
tabel ke NUMBERS
tabel (dan membatasi hasil ke jumlah simpul di setiap baris).
Statistik: (diperbarui)
- Setiap baris memiliki maksimum 30 simpul (rata-rata 4,38 simpul per baris)
- ROADS memiliki 3.997 jalur
- NUMBERS memiliki 30 baris (angka berurutan mulai dari 1)
- Set hasil memiliki 17.536 baris
Namun, kinerjanya buruk (40 detik), dan saya berpikir - apakah ada cara yang lebih elegan untuk melakukan ini? Bagi saya, menggunakan tabel angka dan gabungan silang sepertinya pendekatan yang ceroboh. Apakah ada cara yang lebih baik?
Ketentuan awam akan dihargai; Saya seorang pria Pekerjaan Umum, bukan DBA.
Perbarui # 1:
Jika saya menghapus baris 3 & 4 (serangkaian fungsi terkait X & Y) dari kueri, itu dieksekusi langsung. Tapi tentu saja, saya tidak bisa hanya menghapus garis-garis ini, saya perlu kolom X & Y. Jadi ini membuat saya percaya bahwa kinerja lambat ada hubungannya dengan fungsi X & Y.
Namun, jika saya mengekspor poin ke tabel statis, dan kemudian menjalankan fungsi X & Y di atasnya, ini langsung dieksekusi juga.
Jadi, apakah ini berarti bahwa kinerja yang lambat disebabkan oleh fungsi X & Y, kecuali, yah, bukan? Saya bingung.
Perbarui # 2:
Jika saya mengeluarkan X dan Y dari kueri, memasukkannya ke dalam kueri luar, dan menambahkan ROWNUM ke kueri dalam, maka itu jauh lebih cepat (16 detik - diperbarui):
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 menjelaskan mengapa ROWNUM membantu kinerja di sini: Mengapa menambahkan ROWNUM ke permintaan meningkatkan kinerja?
Meskipun peningkatan kinerja ini baik, itu belum cukup baik. Dan saya tidak dapat membantu tetapi berpikir bahwa saya masih belum sepenuhnya memahami cara kerja kueri atau mengapa permintaannya lambat.
Pertanyaannya masih ada: apakah ada cara yang lebih baik?