Informix

Informix

Connect with Db2, Informix, Netezza, open source, and other data experts to gain value from your data, share insights, and solve problems.

 View Only
Expand all | Collapse all

Row count by rowid does not add up to actual rows

  • 1.  Row count by rowid does not add up to actual rows

    Posted 07/07/26 04:33 PM

    Hi Folks.

    As usual, as have an unusual problem.

    I have an enormous table, over 308 million rows.  I need to perform aome operation on that table but all at once won't work here; long transaction. So I wanted to see if I could break it down by rowid's.  Yes, I  know a rowid (in a regular table) is a composite of (Page address, slot number) but it could still be treated as an integer for my purposes.  seen as an integer, the highest rowid in the table is 2,147,483,412 (Hex: 7FFF FF14).  So I came up with this unioned query to see how many rows there are in each of several classes. Here's the query (with actual table name disguised):

    select "Under 500 Million", count(*) from mytable where rowid > 0          and rowid <= 500,000,000
    union
    select "(500 mil - 1 billion)", count(*) from mytable where rowid > 500,000,000  and rowid <= 1,000,000,000
    union
    select "(1 billion - 1.5 billion)", count(*) from mytable where rowid > 1,000,000,000 and rowid <= 1,500,000,000
    union
    select "(1.5 billion - 2 billion)", count(*) from mytable where rowid > 1,500,000,000 and rowid <= 2,000,000,000
    union
    select "(Over 2 billion)", count(*) from mytable           where rowid > 2,000,000,000
    union
    select "(Gone negative)", count(*) from mytable where rowid <= 0
    ;

    I have inserted commas here to show that I have not make a funny mistake in specifying the big numbers. Here are the counts:

    (constant)                      (count(*))

    (1 billion - 1.5 billion)         39052800
    (1.5 billion - 2 billion)         39052820
    (500 mil - 1 billion)             39052820
    (Gone negative)                          0
    (Over 2 billion)                  11519300
    Under 500 Million                 39052800

    Waitaminit! These add up to about 167 million & change.  How is this possible, when we know the count is over 308 milion?  I think (!!!) I have all possible rowid integer values covered.  That aside, I think it reasonable that ever class has the same number of rows, except the last one, which has no filled up yet.

    What am I missing?  (Yeah, I know about the screws. 🤓)

    Advice, anyone?

    Thanks one and all for a course correction.



    ------------------------------
    +-----------------------------------------------------------+
    | I am pleased to report that I had no problems today. |
    | I had only issues, opportunities, challenges and valuable |
    | learning experiences. |
    +------------------------------------------ Jacob S --------+
    ------------------------------


  • 2.  RE: Row count by rowid does not add up to actual rows

    Posted 07/07/26 04:51 PM

    I have to ask...how did you check that the table has over 308 million records?  A simple count(*) or did you check a catalog table?



    ------------------------------
    Mike Walker
    xDB Systems, Inc
    www.xdbsystems.com
    ------------------------------



  • 3.  RE: Row count by rowid does not add up to actual rows

    Posted 07/07/26 05:35 PM

    Hi Mike.

    First, [Query]->[Info]->[status] gives me that number.

    But w/o running dbaccess, I have my trusty script fragments.sh (published on IIUG repository like 9+ years ago) to keep track as well.

    -- Jacob S



    ------------------------------
    +-----------------------------------------------------------+
    | I am pleased to report that I had no problems today. |
    | I had only issues, opportunities, challenges and valuable |
    | learning experiences. |
    +------------------------------------------ Jacob S --------+
    ------------------------------



  • 4.  RE: Row count by rowid does not add up to actual rows

    Posted 07/07/26 10:17 PM

    This does seem weird.  Assuming that this is a true rowid and not a real column, and that the table has not been partitioned, then I don't see why you would be getting different results for the count and the rowid counts.  The value you show for the max rowid is very close to the max value of an integer, so I am wondering if that is relevant to this.

    What version of Informix are you using?  Is it < version 15?

    What is the rowsize of the records?  Any funky data types in use?

    I'm wondering if it's an issue with the union, even though it shouldn't be.  You could try running it this way to see if it produces a different result:

    select
        case
            when rowid <= 0 then '(Gone negative)'
            when rowid <= 500000000 then 'Under 500 Million'
            when rowid <= 1000000000 then '(500 mil - 1 billion)'
            when rowid <= 1500000000 then '(1 billion - 1.5 billion)'
            when rowid <= 2000000000 then '(1.5 billion - 2 billion)'
            else '(Over 2 billion)'
        end,
        count(*)
    from mytable
    group by 1
    order by 1;



    ------------------------------
    Mike Walker
    xDB Systems, Inc
    www.xdbsystems.com
    ------------------------------



  • 5.  RE: Row count by rowid does not add up to actual rows

    Posted 07/08/26 02:06 AM
    Your problem is the "group by".
    In a fragmented or partitioned table, a rowid is unique within a fragment or partition, containing the pagenum and slot within the page, but not the fragment or partition number.
    So you only count the unique rowids and not all of them.

    select
        case
            when rowid <= 0 then '(Gone negative)'
            when rowid <= 500000000 then 'Under 500 Million'
            when rowid <= 1000000000 then '(500 mil - 1 billion)'
            when rowid <= 1500000000 then '(1 billion - 1.5 billion)'
            when rowid <= 2000000000 then '(1.5 billion - 2 billion)'
            else '(Over 2 billion)'
        end,
        count(*)
    from mytable
    group by 1
    order by 1;

    Mit freundlichen Grüßen / Kind regards
    Gerd Kaluzinski
    Delivery Consultant Data
    IBM Technology Expert Labs
    Phone: +49 175 228 1983                         IBM Deutschland GmbH
    Email: gerd.kaluzinski@de.ibm.com               Mies-van-der-Rohe-Straße 6, 80807 München
    IBM Deutschland GmbH
    Vorsitzender des Aufsichtsrats: Ivo Körner
    Geschäftsführung: Wolfgang Wendt (Vorsitzender), Dr. Andreas Buchelt, Dr. Frank Kohls, Christine Rupp
    Sitz der Gesellschaft: Ehningen / Registergericht: Amtsgericht Stuttgart, HRB 14562





  • 6.  RE: Row count by rowid does not add up to actual rows

    Posted 07/08/26 06:07 AM

    Gerd:

    In a partitioned (fragmented) table the actual physical ROWID is not available simply because there would be duplicates, that is why if you need the functionality of a rowid for a partitioned table you have to create it WITH ROWID which adds an indexed SERIAL type column named rowid, so your comment is incorrect. The fact that Jacob can query the ROWID indicates that either the table is not partitioned or was created WITH ROWID. Given that he is testing for negative rowids I strongly suspect that the table is not partitioned.

    Partitioned tables, indeed all tables, do, however, also support the IFX_ROW_ID pseudo-column which is the phyical address of the row and does include the partnum of the partition that holds the row along with the page number and slot number. Unfortunately IFX_ROW_ID is a string not an integer. 

    Art



    ------------------------------
    Art S. Kagel, President and Principal Consultant
    ASK Database Management Corp.
    www.askdbmgt.com
    ------------------------------



  • 7.  RE: Row count by rowid does not add up to actual rows

    Posted 07/08/26 12:42 PM

    Art and everyone elase telling me how useless rowid is on a partitioned table:

    This table is not partitioned.  I was actually looking for a way to split the task of copying 300+ million rows into a partitioned copy of this table into its partitioned twin.  Thus, rowid is (or should be) a valid way to count rows in each "equivalence class" or rowids.

    As I type this reply, I am running the qury supplied by both Mike and Gerd. And timing it, just for jollies.  Here's the result, with the table name censored, of course:

    select
        case
            when rowid <= 0 then '(0:Gone negative)'
            when rowid <= 500000000  then '(1: Under 500 Million)'
            when rowid <= 1000000000 then '(2: 500 mil - 1 billion)'
            when rowid <= 1500000000 then '(3: 1 billion - 1.5 billion)'
            when rowid <= 2000000000 then '(4: 1.5 billion - 2 billion)'
            else                          '(5: Over 2 billion)'
        end category,
        count(*) frquency
      from <mytable>
     group by 1
     order by 1 ;

    The query ran for 19 minutes and then returned:

    category                             frquency

    (1: Under 500 Million)              308752270

    1 row(s) retrieved.

    What a colossal joke on me, espececially after I had previously selected max(rowid) and gotten a number in the 2-billion range.

    Conclusion (which I had previously concluded): Rowid is interpreted in a funny way internally.  It can not be used as a class of rows.  Fortunately, the table has indexed columns that can be used for splitting the task.

    Surprising numbers but I'd call this the end of the thread.  Lesson learned: Don't use rowid as an integer.  (How does FourGen get away with it?)



    ------------------------------
    +-----------------------------------------------------------+
    | I am pleased to report that I had no problems today. |
    | I had only issues, opportunities, challenges and valuable |
    | learning experiences. |
    +------------------------------------------ Jacob S --------+
    ------------------------------



  • 8.  RE: Row count by rowid does not add up to actual rows

    Posted 07/10/26 09:47 AM
    Edited by Andreas Legner 07/10/26 09:47 AM

    How wide are this table's rows? And how many pages has it got allocated? (oncheck -pt <db>:<tab>   ->    first (DATA) partition would have both these info points)

    Rowid 500000000  = 0x1dcd6500, so page 0x1dcd65 = 1953125  -  if this partition has below these nearly 2mio pages allocated or, technically, if the last row is on a page below this limit, the result of this CASE query would be plausible.

    If not, though, something's indeed fishy here...

    Forgot to mention:  what's the partition's page size?



    ------------------------------
    Andreas Legner
    Informix Dev
    HCL Software
    ------------------------------



  • 9.  RE: Row count by rowid does not add up to actual rows

    Posted 07/10/26 10:18 AM
    Andreas asked:
    • How wide are this table's rows?
      On the order of 80 bytes
    • And how many pages has it got allocated?
      Nearing 16 million.  Whoops!
    This is the reason I created a partitioned twin table, partitioned by some column mod-4.  But the logistics of copying the original data into the twin - that was my motivation for looking to splitting the job (not the table) by rowid.

    I have abandoned that idea but I did, apparently, ignite a storm of speculation.  I have found other ways to split the job into manageable segments.

    Thanks.
    • Jacob S





  • 10.  RE: Row count by rowid does not add up to actual rows

    Posted 07/10/26 09:24 AM

    For sure if the table is partitioned the originally shared query will fail to return the correct number of rows as it doesn't take into account the duplicate rowid's.  If the UNION's where UNION ALL it would likely work.  That being said the Suggested use of the Case and Group By could work too (cleaner to read).  

    Hope one of these solutions finds you well. 

    Eric Rowell



    ------------------------------
    Eric Rowell
    ------------------------------



  • 11.  RE: Row count by rowid does not add up to actual rows

    Posted 07/10/26 12:12 PM

    Eric:

    While Jacob has solved his original problem differently, I have to respond to you and the others who commented on ROWIDs for partitioned tables. Let me repeat my previous post:

    THERE ARE NO ROWIDs AVAILABLE FOR A PARTITIONED TABLE! At least not "real" ROWIDs simply because of the duplicates you cannot query the actual ROWID for a partitioned table, you would get an error if you tried. If and only if the partitioned table was created WITH ROWID it will have a hidden column named rowid, however, that is NOT a ROWID in the sense of a physical row location, but rather a simple SERIAL type column with an index, so there will be no duplicate values!

    Also, Jacob did state that he was trying to find a way to copy smaller numbers of rows from a non-partitioned table to a new partitioned version and had been attempting to see if he could use ranges of ROWIDs to copy subsets of the data.

    I probably should have just reminded Jacob that this is exactly what my dbcopy utility is all about!

    Art



    ------------------------------
    Art S. Kagel, President and Principal Consultant
    ASK Database Management Corp.
    www.askdbmgt.com
    ------------------------------



  • 12.  RE: Row count by rowid does not add up to actual rows

    Posted 07/13/26 11:57 AM
    Again, this is a segue from the original question but to reply to Art:

    I indeed needed the reminder about dbcopy but not every host in my environment has the CSDK installed so  can compile it.  That said, I came up with a scheme to:
    1. Use a query to generate insert into <target> select from <source> where <date-clause>; statements, date-by-date.  Something like 12,000 SQL commands
    2. Run that monster scripts.  Here's what some of that output looks like; it's running now on a test server

    insert into <target> select sti.* from <source> where <join condition> and stx.post_date = '2010/10/20';
    33662 row(s) inserted.

    insert into <target> select sti.* from<source> where <join condition>  and stx.post_date = '2010/10/21';
    36805 row(s) inserted.

    insert into <target> select sti.* from <source> where <join condition> and stx.post_date = '2010/10/22';
    21219 row(s) inserted.

    Each insert is a singleton transaction so no worries about long transactions.  But the log-backup is certainly being kept busy!

    BTW, This is zooming through and thousands of rows per sec.  I would have liked to pipe the <inserted> messages (in stderr?) through a filter that inserts a time stamp at the start of each line, so that I can really gauge rows/second. (fcopy-table.pl does this to the microsecond but that was built in when I had more time to develop it.) Does dbcopy provide this luxury?  I think I'll see if I can compile it on an application development host and copy it where it's needed.

    In any case, I think it's time to put this thread to bed. 

    • Jacob S






  • 13.  RE: Row count by rowid does not add up to actual rows

    Posted 07/13/26 02:45 PM

    Jacob:

    You may have to compile the package with -static if the production system doesn't have the CSDK nor the iConnect libraries installed.

    Yes, dbcopy does optionally report what you are looking for:

    -G - Print data copy rate in rows per second and total copy time.

    $ dbcopy -d art -t extents3 -T extents_2 -G
    Selecting data from art@elendil:extents3 with:
    SELECT * FROM extents3;
    Inserting data to art@elendil:extents_2 with: 
    INSERT INTO extents_2 ( 
    dbsname, 
    tabname, 
    chunk, 
    offset, 
    size, 
    truth, 
    id
    ) values (
    ?, ?, ?, ?, ?, ?, ? );
    Committed: 130000, Rows/sec: 43675
    Input:  138918 records.
    Copied: 138918 records to art@elendil:extents_2.
      Runtime:       3.18 seconds.
      Copy rate: 43742 rows per second.
    Logged: 0 records to error log.



    ------------------------------
    Art S. Kagel, President and Principal Consultant
    ASK Database Management Corp.
    www.askdbmgt.com
    ------------------------------



  • 14.  RE: Row count by rowid does not add up to actual rows

    Posted 07/08/26 08:37 AM

    Hi,

    Is the table partitioned, if so how?

    Try individual selects without the union, same values?

    set isolation to dirty read;

    select count(*) from table;

    too

    Regards,
    David. 

    Regards,
    David.



    ------------------------------
    David Williams
    Senior Database Platform Engineer
    Flutter
    London
    ------------------------------