Faster alternative in Oracle to SELECT COUNT(*) FROM sometable

前端 未结 11 524
被撕碎了的回忆
被撕碎了的回忆 2020-11-29 21:57

I\'ve notice that in Oracle, the query

SELECT COUNT(*) FROM sometable;

is very slow for large tables. It seems like the database it actual

相关标签:
11条回答
  • 2020-11-29 22:44

    Think about it: the database really has to go to every row to do that. In a multi-user environment my COUNT(*) could be different from your COUNT(*). It would be impractical to have a different counter for each and every session so you have literally to count the rows. Most of the time anyway you would have a WHERE clause or a JOIN in your query so your hypothetical counter would be of litte practical value.

    There are ways to speed up things however: if you have an INDEX on a NOT NULL column Oracle will count the rows of the index instead of the table. In a proper relational model all tables have a primary key so the COUNT(*) will use the index of the primary key.

    Bitmap index have entries for NULL rows so a COUNT(*) will use a bitmap index if there is one available.

    0 讨论(0)
  • 2020-11-29 22:44

    This worked well for me

    select owner, table_name, nvl(num_rows,-1) 
    from all_tables 
    --where table_name in ('cats', 'dogs')
    order by nvl(num_rows,-1) desc
    

    from https://livesql.oracle.com/apex/livesql/file/content_EPJLBHYMPOPAGL9PQAV7XH14Q.html

    0 讨论(0)
  • 2020-11-29 22:47

    If you want just a rough estimate, you can extrapolate from a sample:

    SELECT COUNT(*) * 100 FROM sometable SAMPLE (1);

    For greater speed (but lower accuracy) you can reduce the sample size:

    SELECT COUNT(*) * 1000 FROM sometable SAMPLE (0.1);

    For even greater speed (but even worse accuracy) you can use block-wise sampling:

    SELECT COUNT(*) * 100 FROM sometable SAMPLE BLOCK (1);

    0 讨论(0)
  • 2020-11-29 22:51

    The fastest way to get a count of a table is exactly what you did. There are no tricks you can do that Oracle doesn't already know about.

    There are somethings you have not told us. Namely why do you think think this should be faster?

    For example:

    1. Have you at least done an explain plan to see what Oracle is doing?
    2. How many rows are there in this table?
    3. What version of Oracle are you using? 8,9,10,11 ... 7?
    4. Have you ever run database statistics on this table?
    5. Is this a frequently updated table or batch loaded or just static data?
    6. Is this the only slow COUNT(*) you have?
    7. How long does SELECT COUNT(*) FROM Dual take?

    I'll admit I wouldn't be happy with 41 seconds but really WHY do you think it should be faster? If you tell us the table has 18 billion rows and is running on the laptop you bought from a garage sale in 2001, 41 seconds is probably not that far outside "good as it will get" unless you get better hardware. However if you say you are on Oracle 9 and you ran statistics last summer well you'll probably get a different suggestions.

    0 讨论(0)
  • 2020-11-29 22:52

    There was a relevant answer from Ask Tom published in April 2016.

    If you have sufficient server power, you can do

    select /*+ parallel */ count(*) from sometable
    

    If you are just after an approximation, you can do :

    select 5 * count(*) from sometable sample block (10);
    

    Also, if there is

    1. a column that contains no nulls, but is not defined as NOT NULL, and
    2. there is an index on that column

    you could try:

    select /*+ index_ffs(t) */ count(*) from sometable  t where indexed_col is not null
    
    0 讨论(0)
提交回复
热议问题