Fairly depth analysis ORACLE ROWNUM

 

About Oracle's rownum is no stranger to a lot of people said to be a pseudo column after the query results , starting from 1, when used filters must wait rownum starts at 1. What a rownum pseudo column, we'll discuss; rownum is from the beginning, but since it is a pseudo-column, Why do I have to start from 1, let's take a little bit of analysis.

This blog focuses on this issue following

①, rownum is brief and what algorithm;

②, because rownum, implementation plan COUNT STOPKEY how it is;

③, the use of the COUNT STOPKEY rownum paging SQL optimization.

0, data preparation

drop table test1 ;

create table test1 as select * from dba_objects;

alter table TEST1 add constraint PK_TEST1 primary key (OBJECT_ID);

drop table test2;

create table test2 as select * from test1 where rownum <100; - only data insertion 99

1 What, a beauty leads to the question is rownum

A few days ago, there was beauty raises the question like this:

select * from test2 t where rownum=trunc(dbms_random.value(0,100));

This statement is actually the result is 0-n bar ranged, according to many people's interpretation, must start from 1, with a random number when conditions do rownum filter, returns results only when 0 or 1, greater than 1 is how back thing?

When we do not know why, first of all look at the implementation plan and see how the database is SQL execution of sentence.

Look at the execution plan, quite normal, a drill, can not see the prospect of a solution. Here is a modest but important information, TABLE ACCESS FULL , for a while when we finished rownum algorithm, and then back said.

Then we first discuss what rownum is not it. First of all, I give another definition under rownum, counter! ! !

Brief algorithm, for example:

We first construct a student table,

Students select * from table where gender = male and rownum <4;

Operation process is as follows, though boring, but please read line by line, this place is the key to understanding rownum.

1, rownum defined parameters, the initial value of 1;

2, progressive student table:

    2.1 No school for students does not meet the gender-1, lost;

    No. 2 2.2 Found students, sex satisfied, rownum is 1, less than 4, the data taken out, and the column labeled

At this time, the identification value of the rownum, i.e. 1;

    2.3 continue to find the next line, sex is not satisfied, lost;

    No. 4 2.4 Found students learn, sex satisfied, the value +1 rownum, rownum case is 2, less than 4, the number of

It is removed, and at this time the value identifying the data in the rownum 2;

    No. 5 2.5 Found school students, sex satisfied, the value +1 rownum, rownum case 3, less than 4, the number of

It is removed, and at this time the value identifying the data in the rownum 3;

    2.6 find 6 students, sex is not satisfied, discarded;

    2.7 7 students find sex satisfying, rownum value of +1, then rownum value of 4, the search condition is not satisfied

rownum <4, until now, has been able to meet the conditions of the whole data to find out, the end of the inquiry.

 

Through this operation process, rownum explains why the filter 1 from the start, because it is assumed where rownum = 2,

In that place above 2.2, it is to take the first result that does not meet the conditions of rownum query is over;

Through the above calculation process, which explains why we will call for the rownum pseudo column after the query results after the need to focus on a statement, after the so-called query results, query results are not final, but a progressive search, take when coupled to satisfy the condition (rownum and other conditions are met) data, i.e., above 2.2 , 2.4, 2.5

 

So, we return to the problem of beauty, why not fixed as a result rownum conditions when filtering it with a random number?

At this point the question we are left with the above explanation, TABLE ACCESS FULL up. Because the query process, scan line data, generates a random number, the random number is 1, the result was retained , of course, and returns the amount of data uncertain.

Of course, most large enough amount of data, but the range of the random number is small, the number of rows and generally to a random number = the maximum value. For example the following test1 (data of more than 70,000, the random number 0-100), will generally return to 99;

select * from test1 t where rownum=trunc(dbms_random.value(0,100));

The question then again, 70,000 multiple scans, random number generation chance 1 should be more than 99 times now, in theory, it is about 700 times, and why almost all returned it 99?

My personal guess, Oracle optimized internal processing, even if the maximum number of rows that meet the conditions is greater than the random number, the database only returns the number of rows of random numbers within the maximum. As guess right, please also pointing cattle.

2. The implementation plan COUNT STOPKEY

Execute the following SQL statement

select * from test1 t where  rownum<10;

Here COUNT STOPKEY is [1, a beauty leads to the question of what rownum is [2.7] to find the number 7 student, sex meet, rownum value + 1, then 4, does not satisfy the search condition is rownum rownum <4, cut-off At present, able to meet the conditions of data have all find out, the end of the inquiry. ], That is, after rownum conditions are not satisfied, the query is completed.

3. Use the rownum COUNT STOPKEY paging SQL optimization

In fact, the above we said at length principle rownum, a lot of people that Tucao, is a programmer, but not a pedantic professor, engaged in such algorithms make sense?

The answer is yes, we are here with a SQL query optimization paging rownum, rownum assumptions do not understand the principle, we only rote performance paging wording.

First come two pages of writing, a good a bad performance.

Performance bad wording:

select *

from (select rownum as rn , t1.*

      from test1 t1

      order by t1.object_id asc)

where rn between 11 and 30;

性能好的写法

select *

from (select rownum as rn, t.*

      from(select t1.*

           from test1 t1

           order by t1.object_id asc) t

       where rownum < 30) tt

where rn > 11;

执行时间和逻辑读改善一目了然。

细心的朋友会发现,这里有个 INDEX FULL SCAN,其实之前,我也一直困惑INDEX FULL SCAN的使用场景,因为索引全扫描一般回表产生单块读(不回表就是INDEX FAST FULL SCAN了),全扫描就是全部回表;但是像ORACLE这种大厂,里面的研发人员都是技术相当牛的角色,他们肯定不会留着没有用的处理。看到这种高性能分页写法,还请教了SQL优化牛人落落(罗炳森)老师我才明白索引全扫描的好处,其实就是在分页查询时利用索引的有序配合rownum的COUNT STOPKEY来降低IO,至于索引全扫描还有没有其他的高性能使用场景,也请牛人指教。

发布了51 篇原创文章 · 获赞 4 · 访问量 4218

Guess you like

Origin blog.csdn.net/songjian1104/article/details/103438802