NULL in MySQL (Performance & Storage)
What exactly does null do performance and storage (space) wise in MySQL?
For example:
TINYINT: 1 Byte TINYINT w/NULL 1 byte + somehow stores NULL?
It depends on which storage engine you use.
In MyISAM format, each row header contains a bitfield with one bit for each column to encode NULL state. A column that is NULL still takes up space, so NULL's don't reduce storage. See https://dev.mysql.com/doc/internals/en/myisam-introduction.html
In InnoDB, each column has a "field start offset" in the row header, which is one or two bytes per column. The high bit in that field start offset is on if the column is NULL. In that case, the column doesn't need to be stored at all. So if you have a lot of NULL's your storage should be significantly reduced. See https://dev.mysql.com/doc/internals/en/innodb-field-contents.html
EDIT:
The NULL bits are part of the row headers, you don't choose to add them.
The only way I can imagine NULLs improving performance is that in InnoDB, a page of data may fit more rows if the rows contain NULLs. So your InnoDB buffers may be more effective.
But I would be very surprised if this provides a significant performance advantage in practice. Worrying about the effect NULLs have on performance is in the realm of micro-optimization. You should focus your attention elsewhere, in areas that give greater bang for the buck. For example adding well-chosen indexes or increasing database cache allocation.
Bill's answer is good, but a little bit outdated. The use of one or two bytes for storing NULL applies only to InnoDB REDUNDANT row format. Since MySQL 5.0.3 InnoDB uses COMPACT row format which uses only one bit to store a NULL (of course one byte is the minimum), therefore:
Space Required for NULLs = CEILING(N/8) bytes where N is the number of NULL columns in a row.
- 0 NULLS = 0 bytes
- 1 - 8 NULLS = 1 byte
- 9 - 16 NULLS = 2 bytes
- 17 - 24 NULLS = 3 bytes
- etc...
According to the official MySQL site about COMPACT vs REDUNDANT:
The compact row format decreases row storage space by about 20% at the cost of increasing CPU use for some operations. If your workload is a typical one that is limited by cache hit rates and disk speed, compact format is likely to be faster.
Advantage of using NULLS over Empty Strings or Zeros:
- 1 NULL requires 1 byte
- 1 Empty String requires 1 byte (assuming VARCHAR)
- 1 Zero requires 4 bytes (assuming INT)
You start to see the savings here:
- 8 NULLs require 1 byte
- 8 Empty Strings require 8 bytes
- 8 Zeros require 32 bytes
On the other hand, I suggest using NULLs over empty strings or zeros, because they're more organized, portable, and require less space. To improve performance and save space, focus on using the proper data types, indexes, and queries instead of weird tricks.
More on: https://dev.mysql.com/doc/refman/5.7/en/innodb-physical-record.html
I would agree with Bill Karwin, although I would add these MySQL tips. Number 11 addresses this specifically:
First of all, ask yourself if there is any difference between having an empty string value vs. a NULL value (for INT fields: 0 vs. NULL). If there is no reason to have both, you do not need a NULL field. (Did you know that Oracle considers NULL and empty string as being the same?)
NULL columns require additional space and they can add complexity to your comparison statements. Just avoid them when you can. However, I understand some people might have very specific reasons to have NULL values, which is not always a bad thing.
On the other hand, I still utilize null on tables that don't have tons of rows, mostly because I like the logic of saying NOT NULL.
Update Revisiting this later, I would add that I personally don't like to use 0 instead of NULL in the database, and I don't recommend it. This can easily lead to a lot of false positives in your application if you are not careful.
dev.mysql.com/doc/refman/5.0/en/is-null-optimization.html
MySQL can perform the same optimization on col_name IS NULL that it can use for col_name = constant_value. For example, MySQL can use indexes and ranges to search for NULL with IS NULL