Tham gia chéo trên một bảng số để có được các đỉnh dòng, có cách nào tốt hơn không?


8

Câu hỏi:

Tôi có một bảng không gian (đường kẻ), được lưu trữ bằng SDE.ST_GEOMETRYkiể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.GETVERTICESchứ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_PointNST_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""))"

CROSS JOINSlà các dòng trong ROADSbảng thành một NUMBERSbả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?


Bình luận không dành cho thảo luận mở rộng; cuộc trò chuyện này đã được chuyển sang trò chuyện .
Paul White 9

Câu trả lời:


7

Tôi biết một chút về hiệu suất của Oracle và không có gì nhiều về các loại dữ liệu tùy chỉnh, nhưng tôi sẽ cố gắng cung cấp cho bạn một kế hoạch để cải thiện hiệu suất.

1) Xác minh rằng bạn không thể có được một kế hoạch giải thích.

Bạn có thể nhận được các kế hoạch giải thích ngay cả khi bạn không có phần mềm cơ sở dữ liệu phức tạp. Điều gì xảy ra nếu bạn thực thi set autotrace on explain?

Bạn cũng có thể thử DBMS_XPLAN . Trước tiên, hãy lưu kế hoạch bằng cách gói truy vấn của bạn bằng một vài từ khóa bổ sung:

explain plan for (SELECT... your query goes here); 

Sau đó thực hiện điều này:

SELECT PLAN_TABLE_OUTPUT FROM TABLE(DBMS_XPLAN.DISPLAY());

Có thể cả hai sẽ không hoạt động và bạn thực sự không thể có được một kế hoạch giải thích. Tôi chỉ muốn xác minh rằng vì với một kế hoạch giải thích, cộng đồng sẽ giúp bạn dễ dàng hơn nhiều.

2) Xem xét các yêu cầu.

Bạn nói rằng 20 giây không đủ tốt. Bạn hoặc người khác định nghĩa chính xác những gì là đủ tốt? Có chỗ nào để thương lượng không? Có truy vấn của bạn cần phải chính xác một truy vấn CHỌN? Bạn có thể điền một bảng tạm thời toàn cầu trong một bước và chọn kết quả bạn muốn trong lần tiếp theo không? Bạn có thể tạo một thủ tục được lưu trữ trả về một tập kết quả và gọi đó không?

3) Thiết lập giới hạn dưới cho thời gian cần thiết để hoàn thành truy vấn.

Tôi khuyên bạn nên chạy một truy vấn đơn giản "gian lận" để tìm ra một truy vấn được tối ưu hóa tốt sẽ trông như thế nào. Ví dụ: truy vấn này chỉ nhận được các đỉnh đầu tiên mất bao lâu?

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
          ,1 VERTEX_INDEX
          ,SDE.ST_PointN(a.SHAPE, 1) AS ST_POINT
    FROM  ENG.ROAD a
)
ORDER BY ROAD_ID, VERTEX_INDEX;

Tôi nghi ngờ rằng sẽ cung cấp cho bạn 4000 hàng. Nếu bạn nhân thời gian phản hồi của truy vấn đó với 17,5 / 4 có thể cung cấp cho bạn mức giới hạn thấp hơn trong tổng thời gian thực hiện.

Nếu giới hạn dưới của bạn trong tổng thời gian thực hiện dài hơn thời gian bạn thiết lập ở bước 2 thì bạn cần phải sáng tạo với mô hình dữ liệu của mình bằng cách tính kết quả trước thời hạn và lưu trữ chúng trong bảng hoặc bạn cần đàm phán lại thời gian phản hồi cần thiết.

4) Điểm chuẩn để tìm ra chức năng nào đóng góp nhiều nhất vào thời gian thực hiện của bạn.

Bạn đã đi đúng hướng với Bản cập nhật số 1 nhưng bạn cần cố gắng kiểm soát lượng công việc đang thực hiện. Ví dụ: có thể viết một nhóm các truy vấn tương đối đơn giản thực hiện mỗi chức năng chính xác 10000 lần không? Làm thế nào để thời gian đáp ứng so sánh?

5) Đi làm.

Tùy thuộc vào các yêu cầu được thiết lập ở bước 2 và những gì bạn tìm thấy ở bước 4, hãy thử bất kỳ mẹo nào bạn có thể nghĩ ra để giảm thời gian chạy truy vấn. Bạn có thể tính toán trước kết quả và lưu chúng lại không? Nếu vấn đề liên quan đến số lần các chức năng được thực thi thì gợi ý cụ thể hóa không có giấy tờ có thể hữu ích. Điều đó buộc Oracle phải tạo một bảng tạm thời ẩn đằng sau hậu trường để lưu trữ kết quả. Tôi không biết nó có tương thích với các loại dữ liệu đặc biệt mà bạn đang sử dụng không.

Ví dụ, có thể một cái gì đó như thế này thực hiện tốt hơn? Xin lỗi nếu nó không biên dịch nhưng tôi không có cách nào để kiểm tra.

WITH ROAD_CTE (ROAD_ID, VERTEX_INDEX, SHAPE) AS
(
    SELECT /*+ materalize */
      a.ROAD_ID
    , b.NUMBERS VERTEX_INDEX
    , a.SHAPE
    FROM ENG.ROAD a
    CROSS JOIN ENG.NUMBERS b
    WHERE b.NUMBERS <= SDE.ST_NUMPOINTS(a.SHAPE)
)
, CTE_WITH_ST_POINT (ROAD_ID, VERTEX_INDEX, ST_POINT) AS
(
    SELECT /*+ materalize */
      rcte.ROAD_ID
    , rcte.VERTEX_INDEX
    , SDE.ST_PointN(rcte.SHAPE, rcte.VERTEX_INDEX) ST_POINT
    FROM ROAD_CTE rcte
)
SELECT 
      ROAD_ID
    , VERTEX_INDEX
    , SDE.ST_X(ST_POINT) AS X
    , SDE.ST_Y(ST_POINT) AS Y
FROM CTE_WITH_ST_POINT
ORDER BY ROAD_ID, VERTEX_INDEX;

Nếu bạn vẫn bị mắc kẹt sau tất cả những điều này, tôi nghi ngờ rằng ít nhất nó sẽ cung cấp cho bạn thông tin bổ sung mà bạn có thể chỉnh sửa thành câu hỏi. Chúc may mắn!


2

Tôi đã thử sử dụng CONNECT BY (và DUAL) để xem liệu nó có nhanh hơn không, nhưng không phải (nó giống nhau).

SELECT  ROAD_ID
        ,T.VERTEX_INDEX
        ,SDE.ST_X(SDE.ST_PointN(SHAPE, T.VERTEX_INDEX)) AS X
        ,SDE.ST_Y(SDE.ST_PointN(SHAPE, T.VERTEX_INDEX)) AS Y
FROM    ENG.ROADS 
        CROSS JOIN
            (
            SELECT LEVEL AS VERTEX_INDEX 
            FROM DUAL CONNECT BY LEVEL <= 
                (
                SELECT MAX(SDE.ST_NUMPOINTS(SHAPE)) 
                FROM ENG.ROADS 
                )
            ) T
WHERE    T.VERTEX_INDEX <= SDE.ST_NUMPOINTS(SHAPE)
--removed to do explain plan: ORDER BY ROAD_ID, VERTEX_INDEX

-------------------------------------------------------------------------------------------------------
| Id  | Operation                      | Name                 | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT               |                      |   200 | 54800 |    36   (0)| 00:00:01 |
|   1 |  NESTED LOOPS                  |                      |   200 | 54800 |    36   (0)| 00:00:01 |
|   2 |   VIEW                         |                      |     1 |    13 |     2   (0)| 00:00:01 |
|*  3 |    CONNECT BY WITHOUT FILTERING|                      |       |       |            |          |
|   4 |     FAST DUAL                  |                      |     1 |       |     2   (0)| 00:00:01 |
|   5 |     SORT AGGREGATE             |                      |     1 |   261 |            |          |
|   6 |      TABLE ACCESS FULL         | ROAD                 |  3997 |  1018K|    34   (0)| 00:00:01 |
|*  7 |   TABLE ACCESS FULL            | ROAD                 |   200 | 52200 |    34   (0)| 00:00:01 |
-------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
"   3 - filter(LEVEL<= (SELECT MAX(""SDE"".""ST_NUMPOINTS""(""SHAPE"")) FROM "
"              ""ENG"".""ROAD"" ""ROAD""))"
"   7 - filter(""T"".""VERTEX_INDEX""<=""SDE"".""ST_NUMPOINTS""(""ROAD"".""SHAPE""))"

Tôi có ý tưởng từ bài đăng này: Làm thế nào để tính toán phạm vi trong Oracle?


2

Kết quả và phản hồi cho câu trả lời của Joe Obbish :

Lưu ý: Từ đây trở đi, tôi sẽ đề cập đến truy vấn trong Cập nhật # 2 là 'truy vấn'; Tôi sẽ không đề cập đến truy vấn trong câu hỏi ban đầu.

1) Xác minh rằng bạn không thể có được một kế hoạch giải thích.

Tôi không thể thực thi set autotrace on explain. Tôi nhận được lỗi này:ORA-00922: missing or invalid option (#922)

Nhưng tôi có thể thực hiện DBMS_XPLAN. Tôi đã cho rằng tôi sẽ không thể làm điều này. May mắn thay, tôi đã sai. Bây giờ tôi đang chạy giải thích kế hoạch.

2) Xem xét các yêu cầu.

Có truy vấn của bạn cần phải chính xác một truy vấn CHỌN?

Tôi nghĩ rằng truy vấn không cần phải chính xác một truy vấn. Phần mềm tôi đang sử dụng rất hạn chế và không cho phép nhiều câu lệnh chọn.

Bạn đã xác định chính xác yêu cầu của bạn là gì?

  • Truy vấn sẽ được sử dụng để cập nhật tọa độ đỉnh sau khi chỉnh sửa được thực hiện cho hình dạng đường. Điều này thường xảy ra với một dòng duy nhất tại một thời điểm, hoặc có thể là hàng chục dòng, nhưng không có khả năng hàng ngàn dòng. Trong kịch bản này, hiệu suất hiện tại của truy vấn sẽ đầy đủ.
  • Truy vấn cũng sẽ được sử dụng để xây dựng hình dạng đường mới cho tất cả 3.805 dòng (điều này có liên quan đến chủ đề của phân đoạn động / tham chiếu tuyến tính ). Điều này sẽ xảy ra khi đang di chuyển, vì vậy hiệu suất là rất quan trọng. Truy vấn có thể sẽ cần phải thực hiện trong vòng chưa đầy 5 giây.

3) Thiết lập giới hạn dưới cho thời gian cần thiết để hoàn thành truy vấn.

Truy vấn đỉnh đầu tiên thực hiện trong 3,75 giây (trả về 3805 hàng, như mong đợi).

3.75 sec * (16495 total / 3805 lines) = 16.25 sec

Kết quả: giới hạn dưới cho tổng thời gian thực hiện dài hơn thời gian tôi thiết lập ở bước 2 (5 giây). Do đó, tôi nghĩ giải pháp là '... sáng tạo với mô hình dữ liệu của mình bằng cách tính kết quả trước thời hạn và lưu trữ chúng trong một bảng' (thời gian phản hồi yêu cầu là không thể thương lượng). Nói cách khác, làm cho một cái nhìn cụ thể hóa.

Ngoài ra, giới hạn dưới 16,25 giây phù hợp với tổng thời gian thực hiện truy vấn trong Cập nhật # 2 (16 giây). Tôi nghĩ rằng điều này chứng tỏ rằng truy vấn của tôi được tối ưu hóa hoàn toàn, dựa trên các chức năng và dữ liệu mà tôi phải làm việc.

4) Điểm chuẩn để tìm ra chức năng nào đóng góp nhiều nhất vào thời gian thực hiện của bạn.

Tôi đã tạo hai bảng (cả hai đều chứa 10.000 hàng): ROADS_BMROADS_STARTPOINT_BM. Tôi đã chạy các truy vấn đơn giản trên các bảng bằng cách sử dụng từng hàm có liên quan. Đây là kết quả:

               +-----------+------------------+---------------------------------------------------------------------------+
               | TIME(sec) | RETURN TYPE      | QUERY                                                                     |
+--------------+-----------+------------------+---------------------------------------------------------------------------+
| ST_X         | < 0.5     | Double precision | SELECT ROAD_ID FROM (                                                     |
|              |           | (Number)         | SELECT ROAD_ID, SDE.ST_X(SHAPE) AS X FROM ENG.ROADS_STARTPOINT_BM         |
|              |           |                  | ) WHERE X IS NOT NULL ORDER BY ROAD_ID                                    |
+--------------+-----------+------------------+---------------------------------------------------------------------------+
| ST_Y         | < 0.5     | Double precision | SELECT ROAD_ID FROM (                                                     |
|              |           | (Number)         | SELECT ROAD_ID, SDE.ST_Y(SHAPE) AS Y FROM ENG.ROADS_STARTPOINT_BM         |
|              |           |                  | ) WHERE Y IS NOT NULL ORDER BY ROAD_ID                                    |
+--------------+-----------+------------------+---------------------------------------------------------------------------+
| ST_NumPoints | < 0.5     | Integer          | SELECT ROAD_ID FROM (                                                     |
|              |           |                  | SELECT ROAD_ID, SDE.ST_NumPoints(SHAPE) AS NUM_POINTS FROM ENG.ROADS_BM   |
|              |           |                  | ) WHERE NUM_POINTS IS NOT NULL ORDER BY ROAD_ID                           |
+--------------+-----------+------------------+---------------------------------------------------------------------------+
| ST_PointN*   | **9.5**   | ST_POINT         | SELECT ROAD_ID FROM (                                                     |
|              |           | (ST_GEOMETRY     | SELECT ROAD_ID, SDE.ST_PointN(SHAPE,1) AS ST_POINT FROM ENG.ROADS_BM      |
|              |           | subclass)        | ) WHERE ST_POINT IS NOT NULL ORDER BY ROAD_ID                             |
+--------------+-----------+------------------+---------------------------------------------------------------------------+

Tài liệu chức năng: ST_X , ST_Y , ST_NumPoints , ST_PointN

Kết quả? ST_PointNlà vấn đề Thời gian phản hồi 9,5 giây của nó rất tệ so với các chức năng khác. Tôi cho rằng điều này làm cho một chút ý nghĩa mặc dù. ST_PointNtrả về một ST_POINTkiểu dữ liệu hình học, mà phải khá phức tạp so với các hàm khác trả về một số đơn giản.

Lưu ý: ST_PointNlà khó khăn. Đó là kiểu trả về ST_POINT, mà phần mềm của tôi không biết cách xử lý trong tập kết quả : ORA-24359: OCIDefineObject not invoked for a Object type or Reference.

Để giải quyết vấn đề này, tôi đặt nó trong một truy vấn nội tuyến để ngăn cột được trả về tập kết quả. Nhưng khi tôi làm điều đó, truy vấn không thực sự xử lý cột, điều này đánh bại mục đích của thử nghiệm. Vì vậy, tôi kiểm tra nếu nó là null trong truy vấn bên ngoài : WHERE ST_POINT IS NOT NULL ORDER BY RDSEC. Bằng cách này, tôi đảm bảo rằng ST_PointNhàm thực sự đang được sử dụng, mà không trả nó về tập kết quả.

Và tất nhiên, tôi muốn thực hiện một thử nghiệm táo, vì vậy tôi cũng thực hiện cùng một loại truy vấn nội tuyến cho các chức năng khác (mặc dù nó không cần thiết về mặt kỹ thuật).

5) Đi làm.

Dựa trên các bước 2, 3 & 4, đây là những phát hiện của tôi:

  • Vấn đề là ST_PointNchức năng. Nó chậm. Tôi không nghĩ rằng tôi có thể làm được nhiều điều về điều này. Khác với việc cố gắng lập trình lại hoàn toàn / tái tạo chức năng với hy vọng rằng tôi có thể làm tốt hơn các chuyên gia đã thực hiện nó. Không chính xác thực tế.
  • Để đạt được hiệu suất mà tôi yêu cầu, tôi sẽ cần tính toán trước truy vấn trong bảng hoặc dạng xem cụ thể.
  • Theo như '.. các mẹo mà bạn có thể nghĩ ra để giảm thời gian chạy truy vấn', tôi có thể loại bỏ một số đỉnh trong các dòng dài hơn. Điều này sẽ cho phép tôi xóa một vài hàng khỏi bảng NUMBERS (hiện có 30 hàng). Điều này sẽ tăng tốc độ tham gia (mặc dù bất kỳ hiệu suất nào đạt được sẽ là tối thiểu). Tôi cũng nên xem lại tất cả các chỉ mục bảng, mặc dù thực tế là các vấn đề về hiệu suất của tôi không liên quan đến chỉ mục / tham gia.
  • Dựa trên thử nghiệm, tôi không nghĩ vấn đề '... liên quan đến số lần các chức năng được thực thi'.
  • Truy vấn CTE được cung cấp ở # 5 được biên dịch tốt (tôi rất ấn tượng rằng Joe đã có thể thực hiện điều này). Đáng ngạc nhiên, mặc dù thời gian thực hiện là 30 giây, đó không phải là một sự cải thiện. Tôi đoán ST_PointNlà để đổ lỗi cho điều đó quá. Truy vấn CTE không phải là một sự lãng phí; Tôi đã học được rất nhiều chỉ bằng cách sử dụng nó.

6) Kết luận.

Tôi hài lòng rằng tôi đã tối ưu hóa truy vấn nhiều nhất có thể. Tôi sẽ thiết lập tính toán trước và chuyển sang điều tiếp theo. Xin chân thành cảm ơn Joe Obbish; Tôi đã học được một tấn từ các bước anh ấy cung cấp.

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.