In 2018, does it still hold true that MySQL (InnoDB) CHAR performs better VARCHAR speed-wise?

I've only found a performance comparison explanation that is 7 year old. I've checked the official MySQL 8 CHAR vs VARCHAR but the article speaks about storage only, not about performance. I've also read a notice that VARCHAR causes some problems with table fragmentation (see the very 1st comment to this answer.

有帮助吗?

解决方案

I seriously doubt that it ever held true for InnoDB. Even for MyISAM (which really can have FIXED length rows) it was rarely true.

Roughly speaking, this is the order (most overhead first)

  1. Disk hit(s).
  2. Locate the record(s).
  3. Parse the record (split it into columns).
  4. Apply functions and evaluate expressions.

If the data is bigger (as in CHAR being padded), the #1 is impacted. The rest pales into insignificance.

Note: There are 4 flavors of InnoDB ROW_FORMAT.

  • For REDUNDANT, a CHAR(100) CHARACTER SET utf8mb4 always takes 400 bytes.
  • For COMPACT or DYNAMIC, it takes between 100 and 400 bytes.
  • For COMPRESSED, the padding spaces are highly compressible, but still take some space.

Allegedly, the "fixed" size of a CHAR (which, is not all that fixed), tends to prevent block splits. But I kinda doubt it.

My Rule of Thumb: CHAR should almost always be restricted to truly fixed length strings, and most of them are hex or ascii:

country_code CHAR(2) CHARACTER SET ascii
british_postal_code CHAR(6) CHARACTER SET ascii
zip5 CHAR(5) CHARACTER SET ascii
md5 CHAR(32) CHARACTER SET ascii  -- UNHEX() into BINARY(16) is tighter
base64 CHAR(?) CHARACTER SET ascii COLLATION ascii_bin  -- need case-significance

Note: latin1 works equally well as ascii, the 8.0 default of utf8mb4 does not.

(See also my answer to the first link. It starts "Most of the answers in this thread are 5 years old, written before InnoDB and utf8 were defaults. So, let me start over..")

其他提示

There is insignificant difference especially considering CHAR has a maximum length of 255 (VARCHAR is 64K). With the effective equivalent limited to 255 that is a very quick comparison in the case of this field being used as join criteria.

The fragmentation is no longer an consideration as <768 bytes is stored inline. This is still strictly possible in utf8mb4, "InnoDB encodes fixed-length fields greater than or equal to 768 bytes in length as variable-length fields"1 so no difference between CHAR and VARCHAR.

许可以下: CC-BY-SA归因
不隶属于 dba.stackexchange
scroll top