rownum / fetch first n rows

安稳与你 提交于 2021-01-28 12:58:38

问题


select * from Schem.Customer 
  where cust='20' and cust_id >= '890127'
  and rownum between 1 and 2 order by cust, cust_id;

Execution time appr 2 min 10 sec

   select * from Schem.Customer where cust='20' 
   and cust_id >= '890127' 
   order by cust, cust_id fetch first 2 rows only ;

Execution time appr 00.069 ms

The execution time is a huge difference but results are the same. My team is not adopting to later one. Don't ask why.

So what is the difference between Rownum and fetch first 2 rows and what should I do to improve or convince anyone to adopt.

DBMS : DB2 LUW


回答1:


Although both SQL end up giving same resultset, it only happens for your data. There is a great chance that resultset would be different. Let me explain why.

I will make your SQL a little simpler to make it simple to understand:

SELECT * FROM customer
WHERE ROWNUM BETWEEN 1 AND 2;

In this SQL, you want only first and second rows. That's fine. DB2 will optimize your query and never look rows beyond 2nd. Because only first 2 rows qualify your query.

Then you add ORDER BY clause:

SELECT * FROM customer
WHERE ROWNUM BETWEEN 1 AND 2;
ORDER BY cust, cust_id;

In this case, DB2 first fetches 2 rows then order them by cust and cust_id. Then sends to client(you). So far so good. But what if you want to order by cust and cust_id first, then ask for first 2 rows? There is a great difference between them.

This is the simplified SQL for this case:

SELECT * FROM customer
ORDER BY cust, cust_id
FETCH FIRST 2 ROWS ONLY;

In this SQL, ALL rows qualify the query, so DB2 fetches all of the rows, then sorts them, then sends first 2 rows to client.

In your case, both queries give same results because first 2 rows are already ordered by cust and cust_id. But it won't work if first 2 rows would have different cust and cust_id values.

A hint about this is FETCH FIRST n ROWS comes after order by, that means DB2 orders the result then retrieves first n rows.




回答2:


Excellent answer here: https://blog.dbi-services.com/oracle-rownum-vs-rownumber-and-12c-fetch-first/

Now the index range scan is chosen, with the right cardinality estimation. So which solution it the best one? I prefer row_number() for several reasons: I like analytic functions. They have larger possibilities, such as setting the limit as a percentage of total number of rows for example. 11g documentation for rownum says: The ROW_NUMBER built-in SQL function provides superior support for ordering the results of a query 12c allows the ANSI syntax ORDER BY…FETCH FIRST…ROWS ONLY which is translated to row_number() predicate 12c documentation for rownum adds: The row_limiting_clause of the SELECT statement provides superior support rownum has first_rows_n issues as well

PLAN_TABLE_OUTPUT
SQL_ID 49m5a3f33cmd0, child number 0
-------------------------------------
select /*+ FIRST_ROWS(10) */ * from test where contract_id=500 
order by start_validity fetch first 10 rows only
Plan hash value: 1912639229
--------------------------------------------------------------------------------------
| Id  | Operation                     | Name    | Starts | E-Rows | A-Rows | Buffers |
--------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT              |         |      1 |        |     10 |      15 |
|*  1 |  VIEW                         |         |      1 |     10 |     10 |      15 |
|*  2 |   WINDOW NOSORT STOPKEY       |         |      1 |     10 |     10 |      15 |
|   3 |    TABLE ACCESS BY INDEX ROWID| TEST    |      1 |     10 |     11 |      15 |
|*  4 |     INDEX RANGE SCAN          | TEST_PK |      1 |        |     11 |       4 |
--------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("from$_subquery$_002"."rowlimit_$$_rownumber" <=10)
2 - filter(ROW_NUMBER() OVER ( ORDER BY "TEST"."START_VALIDITY") <=10 )  
4 - access("CONTRACT_ID"=500)


来源:https://stackoverflow.com/questions/47520732/rownum-fetch-first-n-rows

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!