7

We need to add a priority column to a table that gets hit about 250 times a second, approx 170 selects, 125 inserts and 60 updates. The column will be a simple number(1).

The priority does not matter for the inserts or updates i.e. not part of the primary key, which I'll enforce separately.

We basically don't want to have to do an order by over a range scan 170 times a second, as the number executed will drop massively.

Does an index organised table guarantee that priority = 1 will always come before priority = 9 when running the following query:

select *
  from my_table
 where rownum < 2

For slightly more context a typical query would be:

select *
  from my_table
 where mod(to_number(to_char(tstamp,'ss')),1) = 0
   and done is null
   and country = 'gbr'
   and rownum < 2

The pk constraint, for the IOT, would become priority, rest of the pk with a separate constraint on the pk solely for structure. done is null in approximately 99% of the table so this isn't very selective anyway.

Main index used is, I think, country, done, to_number(to_char(tstamp,'ss'), we tested about 20 combinations and this came up top by a long way.

I am completely unwilling to add any time at all to these queries, 0.01s a day added by select is 41 minutes a day. We'd much rather settle for "good enough" than perfection.

Ben
  • 462
  • 4
  • 16

4 Answers4

13

No.

The only thing that guarantees result set order is an ORDER BY clause in your query.

This is a popular question about SQL so it's worth repeating what I've written in response to similar questions about SQL Server and MySQL:

In the SQL world, order is not an inherent property of a set of data. Thus, you get no guarantees from your RDBMS that your data will come back in a certain order -- or even in a consistent order -- unless you query your data with an ORDER BY clause.

In Oracle, an Index-Organized Table (IOT) will minimize the amount of work the database has to do to get you the data sorted in the index's sort order. Though you may find that Oracle tends to return rows selected from an IOT in that same order, you are only guaranteed that order when you query the IOT with an ORDER BY clause.

Nick Chammas
  • 14,810
  • 17
  • 76
  • 124
5

Does an IOT guarantee order in a select?

No, order is not guaranteed without ORDER BY. Ever.

But you can achieve what you want like this:

select * from (select * from my_table order by priority) where rownum < 2;

This will not necessarily cause Oracle to do more work:

create table foo(priority, id, primary key (priority,id)) organization index as
select mod(level,9), level from dual connect by level<=100000;
select /*+ gather_plan_statistics */ *
from (select * from foo order by priority)
where rownum<2;
PRIORITY | ID
-------: | -:
       0 |  9
select * from table(dbms_xplan.display_cursor(null,null,'ALLSTATS LAST'));
| ------------------------------------------------------------------------------------------------- |
| | Id  | Operation         | Name              | Starts | E-Rows | A-Rows |   A-Time   | Buffers | |
| ------------------------------------------------------------------------------------------------- |
| |   0 | SELECT STATEMENT  |                   |      1 |        |      1 |00:00:00.01 |       2 | |
| |*  1 |  COUNT STOPKEY    |                   |      1 |        |      1 |00:00:00.01 |       2 | |
| |   2 |   VIEW            |                   |      1 |      1 |      1 |00:00:00.01 |       2 | |
| |   3 |    INDEX FULL SCAN| SYS_IOT_TOP_26495 |      1 |    100K|      1 |00:00:00.01 |       2 | |
| ------------------------------------------------------------------------------------------------- |
|                                                                                                   |
| Predicate Information (identified by operation id):                                               |
| ---------------------------------------------------                                               |
|                                                                                                   |
|    1 - filter(ROWNUM<2)                                                                           |
|                                                                                                   |

dbfiddle here

The meaning of the COUNT STOPKEY is that Oracle does not have to go through all the rows of the FULL SCAN

Jack Douglas
  • 40,517
  • 16
  • 106
  • 178
2

No. The only way to guarantee the order of results is to add an ORDER BY.

Justin Cave
  • 20,383
  • 2
  • 52
  • 65
2

For Microsoft SQL Server, the answer is also no, and the mechanics of it are pretty interesting. The Books Online page about scanning explains the concept of merry-go-round scans in the Advanced Scanning section:

For example, assume that you have a table with 500,000 pages. UserA executes a Transact-SQL statement that requires a scan of the table. When that scan has processed 100,000 pages, UserB executes another Transact-SQL statement that scans the same table. The Database Engine schedules one set of read requests for pages after 100,001, and passes the rows from each page back to both scans. When the scan reaches the 200,000th page, UserC executes another Transact-SQL statement that scans the same table. Starting with page 200,001, the Database Engine passes the rows from each page it reads back to all three scans. After it reads the 500,000th row, the scan for UserA is complete, and the scans for UserB and UserC wrap back and start to read the pages starting with page 1.

There's more details in the Books Online page.

Brent Ozar
  • 43,325
  • 51
  • 233
  • 390