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
  • 1.  Serial and pseudo-rowid values going negative

    Posted 26 days ago

    Hi again today.

    It is known that when I create a table "with rowid" (or alter fragment .. with rowid) the server create a shadow serial column named rowid and and index named "system-rowid" to go with it.  We have experienced serial values overflowing the 2^31 threshold, resulting in a negative serial value. (Why, oh why, wasn't serial designated as unsigned integer?)  My concern is that, if a table gets gazzilion inserts, the pseudo-rowid could also go negative.  I know some legacy application packages - that get extra speed by using rowid - get cranky with faced with a negative rowid.

    Well, if serial can overflow into the negatives, what's to stop the pseudo rowid from doing the same, evoking the same cranky behavior as when the true rowid looks negative. (Like when the logical page number is over 2^23.)  At least for serial we now have the bigserial (64-bit) data type to forestall the negativity. But what's available for pseudo-rowid?

    Ideas, anyone?

    Thanks!



    ------------------------------
    +-----------------------------------------------------------+
    | 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: Serial and pseudo-rowid values going negative

    Posted 26 days ago

    Jacob:

    I know that this does not fix a problem with 3rd party applications that use ROWID specifically, but for customer developed software and for ad-hoc queries, there is the pseudo-column ifx_row_id which exists for all tables, even partitioned tables, without adding any hidden column like the WITH ROWIDS feature:

    $ dbaccess art -
     
    Database selected.
     
    > select ifx_row_id from systables limit 5;
    ifx_row_id                                    
     
    1049283:769                                  
    1049283:770                                  
    1049283:771                                  
    1049283:772                                  
    1049283:773                                  
     
    5 row(s) retrieved.
     

    The ifx_row_id was introduced a LONG time ago (so long I can't find anyone who remembers what version it appears in first). As long as you are using v14.10.FC6 or later, SELECT  FROM table WHERE ifx_row_id = '1049283:769'; is at least as faster as SELECT  * FROM table WHERE ROWID = 769; (and can be faster) because, like the real ROWID pseudo-column, it represents the physical address of the row on disk (or more accurately the physical location of the row's slot table entry on disk). Unlike ROWID the pseudo-column which does not contain the partition number, and the WITH ROWID hidden column which is just an indexed SERIAL column, ifx_row_id exists and works just fine even for partitioned tables:

    create large table "art".extents_2 
      (
        dbsname lvarchar(10000),
        tabname lvarchar(10000),
        chunk integer,
        offset integer,
        size bigint,
        truth "informix".boolean 
            default 't',
        id bigserial not null 
      fragment by round robin partition p1 in datadbs_2, partition p2 in datadbs_2,
         partition p3 in datadbs_2
      extent size 57412 next size 16 lock mode row statchange 0;
    > select first 5 ifx_row_id from extents_2;
    ifx_row_id                                    
     
    9437281:-9223372036854710271                 
    9437281:-9223372036854710270                 
    9437281:-9223372036854710269                 
    9437281:-9223372036854710268                 
    9437281:-9223372036854710267                 
     
    5 row(s) retrieved.

    Art



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



  • 3.  RE: Serial and pseudo-rowid values going negative

    Posted 26 days ago
    You could, of course, use a subquery in the FROM clause to map ifx_row_id as rowid:

    > select *  
    > from (
    >     select offset, ifx_row_id as rowid from extents_2 );

         offset rowid                                        

          59871 9437281:-9223372036854710271                
          59359 9437281:-9223372036854710270                
           8030 9437281:-9223372036854710269                
           1655 9437281:-9223372036854710268                
         490298 94379437281, 281:-9223372036854710267                
           8030 9437281:-9223372036854710266                
          55707 9437281:-9223372036854710265                
          56995 9437283:-9223372036854710271                
         490282 9437283:-9223372036854710270           
    ...
    BTW, notice that the returned rows have two different partition numbers (9437281 & 9437283) because the rows are being returned in parallel from two different partitions.

    Art

    Art S. Kagel, President and Principal Consultant
    ASK Database Management


    Disclaimer: Please keep in mind that my own opinions are my own opinions and do not reflect on the IIUG, nor any other organization with which I am associated either explicitly, implicitly, or by inference.  Neither do those opinions reflect those of other individuals affiliated with any entity with which I am affiliated nor those of the entities themselves.









  • 4.  RE: Serial and pseudo-rowid values going negative

    Posted 26 days ago

    Oh, forgot, I know that still requires changing code to handle a 46byte string instead of a 4 byte integer:

    ~$ sqlstruct -n fred -d art
    > select ifx_row_id from systables;
     
    typedef struct fred_s {
        char ifx_row_id[46];
    } fred_t, *fred_tp;

    >

    Art



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



  • 5.  RE: Serial and pseudo-rowid values going negative

    Posted 26 days ago
    Bad Art .... I see a Boolean - the datatype of Satan 

    Cheers
    Paul

    Paul Watson
    Oninit LLC
    +1-913-387-7529
    www.oninit.com
    Oninit®️ is a registered trademark of Oninit LLC





  • 6.  RE: Serial and pseudo-rowid values going negative

    Posted 25 days ago
    I built that table to test SMALL versus LARGE table performance. I needed something to slow queries down!  ��


    Art S. Kagel, President and Principal Consultant
    ASK Database Management


    Disclaimer: Please keep in mind that my own opinions are my own opinions and do not reflect on the IIUG, nor any other organization with which I am associated either explicitly, implicitly, or by inference.  Neither do those opinions reflect those of other individuals affiliated with any entity with which I am affiliated nor those of the entities themselves.









  • 7.  RE: Serial and pseudo-rowid values going negative

    Posted 25 days ago

    Art,

    This is SUCH a revelation to me! It won't help for my situation because our legacy application is rife with zillions of explicit references to rowid itself.  Hence, we have no choice but to use the pseudo rowid. But it is great to know.

    Stepping off on a tangent here: For your example,  I must presume that your example was done on release 15.x. Why assume so?  Because below release 15, the rowid part of the first row in a table would be 257 == 0x101; page 1, slot 1.  In your example, the rowid part of the first row was the insanely negative -9223372036854710271. In hex, that is 0x8000 0000 0001 0001.  Still page 1, slot 1 but the slot number is a 16-bit number rather than 8 bit.  In this case 65,537

    So here's my segue question: Why is the high-order bit of that rowid set to 1?  (I'm sure that is explained on one of myriad help pages.  But which one?)

    Again, thanks for that eye-opener.



    ------------------------------
    +-----------------------------------------------------------+
    | 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: Serial and pseudo-rowid values going negative

    Posted 25 days ago

    Art may be already drafting an answer here but I'll jump in anyway. Internally we pass rowids around in the code everywhere. Parameters to routines, return values from routines. We have zillions of variables that have to contain them. Rather than attempt to have separate 4-byte integer variables/parameters to store legacy rowids along with 8-byte integer variables/parameters to store large rowids, we standardized all rowid containers as 8-byte integers. This made the code much, much simpler and easier to maintain.

    But given an 8-byte integer rowid value we need a way to distinguish between legacy and large rowids. That's the purpose of setting the sign bit for large rowids. Capacity is already so huge that we aren't sacrificing much by reserving that highest-order bit.



    ------------------------------
    John Lengyel
    ------------------------------



  • 9.  RE: Serial and pseudo-rowid values going negative

    Posted 25 days ago

    Again, BEAUTIFUL!

     

    +-----------------------------------------------------------+

    | I am pleased to report that I had no problems today.      |

    | I had only issues, opportunities, challenges and valuable |

    | learning experiences.                                     |

    +-----------------------------------------------------------+

     






  • 10.  RE: Serial and pseudo-rowid values going negative

    Posted 25 days ago
      |   view attached

    It does make all large rowids ugly, I get it. But keep in mind that even in pre-V15 versions, once you go above 8,388,607 (0x7FFFFF) pages in a legacy table those rowids are going negative too. FWIW I use the following (rough) C program to convert large rowid values from hex to decimal and vice-versa on the command line. It doesn't quite work for negative legacy rowids but it's still useful there.

    Usage:

    rid <rowid>

    As in:

    rid
    -9223372036854710271
    or
    rid
    0x8000000000010001



    ------------------------------
    John Lengyel
    ------------------------------

    Attachment(s)

    c
    rid.c   6 KB 1 version


  • 11.  RE: Serial and pseudo-rowid values going negative

    Posted 25 days ago

    Jacob:

    You are correct, I am working with v15.0.1.0.1 here. You will notice that the first example I selected data from systables and, even in v15, all catalog tables are SMALL (aka legacy style) tables so the rowid portion of the ifx_row_id was still a small positive number while selecting from the extents_2 table, which is a partitioned LARGE table has those wacky rowid portions. The reason is that setting the high bit indicates that the rowid is from a LARGE table rather than from a SMALL table since all rowids in v15 are 8 bytes rather than 4 bytes, as John wrote.

    Art



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