Re: storage engine: understanding the row format

Christoph Rupp <[email protected]> Thu, 19 May 2016 14:42:54 +0200
Newsgroups gmane.comp.db.mysql.devel
Message-ID <CAE6Xdb5uwt7uj5SRFNz_YXBMrBm1XcDTis5GrYS+S24J+RFFKg@mail.gmail.com>
Hi =C3=98ystein,

thanks for the fast and helpful reply!

I assume that table->s->null_bytes tells me how many bytes are used to
describe the nullable columns?

Best regards
Christoph

2016-05-19 14:34 GMT+02:00 =C3=98ystein Gr=C3=B8vlen <oystein.grovlen@oracl=
e.com>:
> Hi Christoph,
>
> On 19. mai 2016 14:15, Christoph Rupp wrote:
>>
>> Hi,
>>
>> If a row has variable-length blobs (fields of type
>> MYSQL_TYPE_VARCHAR), then the serialized row stores the full length of
>> the blob, even if most bytes are unused. In such cases, i'd like to
>> "compress" the row before writing it to disk.
>
>
> Note that VARCHAR and BLOB are different types.  Contrary to VARCHAR, for
> blobs, space is not allocated in the internal record buffer, but in separ=
ate
> buffers.
>
>>
>> However, i have a few difficulties understanding the row format. The
>> following two CREATE TABLE statements are relatively similar (the
>> first one creates an additional index). But their first byte differs,
>> and I don't understand why.
>
>
> The index is not the only difference.  Nullability of the value column al=
so
> differs.
>
>>
>> CREATE TABLE test (value VARCHAR(30) NOT NULL, INDEX(value), num
>> INTEGER PRIMARY KEY)
>> INSERT INTO test VALUES("1", 1);
>>
>> (gdb) x/8b buf
>> 0x7fff5000e660:    1    49    -113    -113    -113    -113    -113    -1=
13
>>
>> buf[0] stores the length of 'value', buf[1] stores the data of 'value'.
>>
>> CREATE TABLE test (value VARCHAR(30), num INTEGER PRIMARY KEY)
>> INSERT INTO test VALUES("1", 1);
>>
>> (gdb) x/8b buf
>> 0x7fff50013cf0:    -2    1    49    -113    -113    -113    -113    -113
>>
>> Now buf[1] stores the length and buf[2] stores the data of 'value'.
>>
>> But what is buf[0]?
>
>
> The additional byte(s) is used to record which nullable columns are NULL.
> For tables where there are no nullable columns, there will not be such a
> byte.
>
> Regards,
>
> --
> =C3=98ystein
>
>
>>
>> Is there documentation for the serialized row format?
>>
>> Thanks
>> Christoph
>>
>> PS: here's the code that i currently use:
>>
>> static inline ups_record_t
>> pack_record(TABLE *table, uint8_t *buf, uint8_t *arena)
>> {
>>    assert(!row_is_fixed_length(table));
>>
>>    uint8_t *src =3D buf;
>>    uint8_t *dst =3D arena;
>>
>>    // copy the first byte - whatever it is
>>    // this causes problems because in some cases there is no "first byte=
"!
>>    *dst =3D *src;
>>    dst++;
>>    src++;
>>
>>    for (Field **field =3D table->field; *field !=3D 0; field++) {
>>      uint32_t type =3D (*field)->type();
>>      uint16_t key_size;
>>      uint32_t len_bytes;
>>
>>      if (type =3D=3D MYSQL_TYPE_VARCHAR) {
>>        // see Field_blob::Field_blob() (in field.h) - need 1-4 bytes to
>>        // store the real size
>>        if ((*field)->field_length <=3D 255) {
>>          len_bytes =3D 1;
>>          key_size =3D *src;
>>        }
>>        else if ((*field)->field_length <=3D 65535) {
>>          len_bytes =3D 2;
>>          key_size =3D *(uint16_t *)src;
>>        }
>>        else if ((*field)->field_length <=3D 16777215) {
>>          len_bytes =3D 3;
>>          key_size =3D *src; // TODO implement this
>>        }
>>        else {
>>          len_bytes =3D 4;
>>          key_size =3D *(uint32_t *)src;
>>        }
>>      }
>>      else {
>>        len_bytes =3D 0;
>>        key_size =3D (*field)->key_length();
>>      }
>>
>>      ::memcpy(dst, src, key_size + len_bytes);
>>      src +=3D (*field)->pack_length();
>>      dst +=3D key_size + len_bytes;
>>    }
>>
>>    ups_record_t r =3D ups_make_record(arena, (uint32_t)(dst - arena));
>>    return r;
>> }
>>
>
>
> --
> =C3=98ystein

-- 
MySQL Internals Mailing List
For list archives: http://lists.mysql.com/internals
To unsubscribe:    http://lists.mysql.com/internals