MySQL - How is the row size above 65535 - mysql

I understand that the maximum row limit in mysql is 65535, which is equal to (2 ^ 16) - 1. I also understand that it is bad database design to have extremely long rows like that. However, this is my schema
CREATE TABLE mytable(
a VARCHAR(20000),
b VARCHAR(20000),
c VARCHAR(20000),
d VARCHAR(5535)
) CHARACTER SET=latin1;
This is the output I get
Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535. This includes storage overhead, check the manual. You have to change some columns to TEXT or BLOBs
Let's do the math again
20000 + 20000 + 20000 + 5535 = 65535
which is equal to and does not surpass the limit. For the record, the highest value for column d that works is 5526.
I do not understand where those additional 9 characters come from.

The size of VARCHAR is calculated like this:
len + 1 bytes if column is 0 – 255 bytes, len + 2 bytes if column may require more than 255 bytes
so
CREATE TABLE mytable(
a VARCHAR(20000), -- 20002
b VARCHAR(20000), -- 20002
c VARCHAR(20000), -- 20002
d VARCHAR(5535) -- 5537
) CHARACTER SET=latin1;-- 65543 !!!! 8 Bytes to much
see this https://mariadb.com/kb/en/mariadb/data-type-storage-requirements/

from: http://dev.mysql.com/doc/refman/5.7/en/column-count-limit.html
row length = 1
+ (sum of column lengths)
+ (number of NULL columns + delete_flag + 7)/8
+ (number of variable-length columns)
Try change column type to VARCHAR (20000) NOT NULL

Related

What is the size of a composite index in MySQL/MariaDB

Suppose I have three columns, A, B, C. They each have a range of x, y and z possible values respectively.
Does an index on all three columns have a size proportional to x * y * z?
No. The size of an INDEX is (roughly)
N * L + overhead
N = Number of rows in the entire table.
L = Length (in bytes) of the values in all the columns of the index, plus columns in the PRIMARY KEY.
overhead = various pointer, lengths, padding, etc
Example: CREATE TABLE ... id INT PRIMARY KEY, A INT, INDEX(A) ...
INT is a 4-byte datatype. It can hold more than 4 billion distinct values. If there are 100 rows in the table, let's look at the BTree holding the secondary INDEX(A).
N = 100
L = 4 + 4 -- that bytes, not billions of bytes
N * L = 800, but once the overhead is added, and use the blocking, it will take 16KB. (Note: InnoDB allocates data and indexes in "blocks" of 16KB.)
Now add to that table
city VARCHAR(100), -- average length 10 characters
INDEX(city, A)
N = 100 -- still assuming 100 rows
L = (2+10) + 4 + 4 = 16
total = again, only 1-2 blocks.
The (2+10): 2 for the "length" of the string; 10, on average, for the actual string. (In some cases, the "2" is really "1" and if you are using utf8, each character could be multiple bytes.)
If that table grows to 1 million rows, the index may take 50MB, a lot of it being unavoidable "overhead".
A major exception:
For InnoDB, the size of the PRIMARY KEY is virtually zero since it is "clustered" with the data. Actually, there is about 1% extra for the non-leaf nodes in that BTree and some 'overhead'.

Estimating Column Size

This is what I found in the documentation:
Can you help me interpret the data storage of this table?
Let's say I create a table like this:
create table test.test_1(
value_1 tinyint,
value_2 smallint,
value_3 mediumint
)
insert into test.test_1(value_1, value_2, value_3) values(1,1,1),(2,2,2),(3,3,3);
Are the following statements true if we sum up the data storage in each column:
value_1 total size = 3 bytes
value_2 total size = 6 bytes
value_3 total size = 9 bytes
I understand how to find the total data storage if the column is a string data type, but how do I do this if the data if of the integer or numeric variety?

How to set the maximal size of BLOB column in MySQL?

I want to set the maximal size of a BLOB column to be up to 900KB.
Is there a way similar to the syntax of the other String Data types - for example
c CHAR(7),
vc VARCHAR(50),
pic BLOB (???)
to do this?
From the storage requirements section of the manual, the max size of the following fields:
TINYBLOB : L < 2^8 = 256 Bytes
BLOB : L < 2^16 = 65,536 Bytes
MEDIUMBLOB : L < 2^24 = 16,777,216 Bytes
LONGBLOB : L < 2^32 = 4,294,967,296 Bytes
In order to store 900KB, you would need to use a MEDIUMBLOB at the very minimum.
As far as I know, you can not specify your own size for the field.
With our IBM Database (AS400), it is possible to provide a size to a Blob field.
fieldName Blob(size in bytes)
The maximum Size is then visible like any other length
Screenshot from DBvisualizer:

MySQL Hexadecimal Binary Limit

I have a Table with 2 columns: 'Id' (datatype=INT) , 'Representation' (datatype=binary).
I want to store a hexadecimal value in the form of binary digits in the 'Representation' Column.
What is the Max number of Binary digits that i can store in the 'Representation' column ?
MySql
BINARY
The MySql docs on the binary data type, mention:
The permissible maximum length is the same for BINARY and VARBINARY as it is for CHAR and VARCHAR, except that the length for BINARY and VARBINARY is a length in bytes rather than in characters.
So binary is put on the same level as char, and varbinary as varchar.
The docs on the char data type, mention:
The length of a CHAR column is fixed to the length that you declare when you create the table. The length can be any value from 0 to 255.
So the maximum size for binary is therefore achieved with this:
CREATE TABLE mytable (
id int,
representation binary(255)
)
This corresponds to 255 bytes of data, which corresponds to 510 hexadecimal digits, or 2040 bits.
VARBINARY
The varbinary type can store up to 65,535 bytes, from which the sizes of the other columns must be subtracted. Again, this follows from the docs on varchar:
Values in VARCHAR columns are variable-length strings. The length can be specified as a value from 0 to 65,535. The effective maximum length of a VARCHAR is subject to the maximum row size (65,535 bytes, which is shared among all columns) and the character set used.
So let's say you would need room for about 500 bytes in other columns, then you could defined this table:
CREATE TABLE mytable (
id int, // takes 4 bytes
representation binary(65000),
// other fields come here, taking up less than 532 bytes
)
... you would have 65,000 bytes, i.e. 130,000 hexadecimal digits or 520,000 bits.
SQL Server Binary
The Transact-SQL docs on binary state:
binary [ ( n ) ]
Fixed-length binary data with a length of n bytes, where n is a value from 1 through 8,000. The storage size is n bytes.
This means that with this table definition:
CREATE TABLE mytable (
id int,
representation binary(8000)
)
... you can store 8,000 bytes, i.e. 16,000 hexadecimal digits or 64,000 bits.
Note that the limit for varbinary is the same. The following advise is given in the docs:
Use varbinary when the sizes of the column data entries vary considerably.

How to get the space consumed by a set of records in a table?

I have a table called HUGETABLE. I want to get the size consumed by a set of records in HUGETABLE under some Select where criteria. I am currently using the following query for getting the table size in KBS , is there any Other improved query other than this? :
SELECT SUM(LENGTH(IFNULL(translation_logs.GUID,0))+
LENGTH(IFNULL(HUGETABLE.ID,0))+
LENGTH(IFNULL(HUGETABLE.SEQUENCENO,0))+
LENGTH(IFNULL(HUGETABLE.BID,0))+
LENGTH(IFNULL(HUGETABLE.TID,0))+
LENGTH(IFNULL(HUGETABLE.TABLENAME,0))+
LENGTH(IFNULL(HUGETABLE.MODIFIEDDATE,0))+
LENGTH(IFNULL(HUGETABLE.MODIFIEDBY,0))+
LENGTH(IFNULL(HUGETABLE.UPDATEXML,0))+
LENGTH(IFNULL(HUGETABLE.BESTIDENTIFIERVALUE,0)))/1024 AS "Total Size in KB"
FROM HUGETABLE
WHERE TID = 'myvalue';
and TID is the index field
Instead of making a huge query, you can check via the maximal size of each field. If you have VARCHAR, it'll be a bit difficult and in that case you have to do a selection.
According to this documentation page, an INT takes 4 bytes, a DATE 3 bytes, etc. So with 5 INT (your 5 first fields), 1 DATE and 4 VARCHAR (I'm guessing not sure about your table structure), you just have to do something like:
SELECT 4*5 + 1 * 3 + (LENGTH(TABLENAME)+2) + (LENGTH(MODIFYBY)+2) + ...
FROM HUGETABLE
WHERE TID = 'myvalue';
If you want to also take the space used by the index, it's a bit more difficult, and I'm not informed enough about it.