我知道依赖于正在使用的数据库存储引擎,如果表中的所有行都可以保证长度相同(通过避免可为空的列而不使用任何VARCHAR,TEXT或BLOB专栏)。我不清楚InnoDB在多大程度上适用于它有趣的桌子安排。我们举个例子:我有下表
CREATE TABLE `PlayerGameRcd` (
`User` SMALLINT UNSIGNED NOT NULL,
`Game` MEDIUMINT UNSIGNED NOT NULL,
`GameResult` ENUM('Quit',
'Kicked by Vote',
'Kicked by Admin',
'Kicked by System',
'Finished 5th',
'Finished 4th',
'Finished 3rd',
'Finished 2nd',
'Finished 1st',
'Game Aborted',
'Playing',
'Hide'
) NOT NULL DEFAULT 'Playing',
`Inherited` TINYINT NOT NULL,
`GameCounts` TINYINT NOT NULL,
`Colour` TINYINT UNSIGNED NOT NULL,
`Score` SMALLINT UNSIGNED NOT NULL DEFAULT 0,
`NumLongTurns` TINYINT UNSIGNED NOT NULL DEFAULT 0,
`Notes` MEDIUMTEXT,
`CurrentOccupant` TINYINT UNSIGNED NOT NULL DEFAULT 0,
PRIMARY KEY (`Game`, `User`),
UNIQUE KEY `PGR_multi_uk` (`Game`, `CurrentOccupant`, `Colour`),
INDEX `Stats_ind_PGR` (`GameCounts`, `GameResult`, `Score`, `User`),
INDEX `GameList_ind_PGR` (`User`, `CurrentOccupant`, `Game`, `Colour`),
CONSTRAINT `Constr_PlayerGameRcd_User_fk`
FOREIGN KEY `User_fk` (`User`) REFERENCES `User` (`UserID`)
ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT `Constr_PlayerGameRcd_Game_fk`
FOREIGN KEY `Game_fk` (`Game`) REFERENCES `Game` (`GameID`)
ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=INNODB CHARACTER SET utf8 COLLATE utf8_general_ci
唯一可以为空的列是Notes
,即MEDIUMTEXT。这个表目前有33097行(我欣赏它还很小)。在这些行中,只有61个具有Notes
中的值。我可以看到多少改进,例如,添加一个新表来存储Notes列并在必要时执行LEFT JOIN?
答案 0 :(得分:1)
文本和Blob字段与表分开存储(在磁盘查找时需要额外的值)。每次从表中得到子查询都需要一个临时表,临时表将立即在磁盘上创建,因为mysql无法预测行大小并在内存中保留足够的空间。
如果Notes字段的大小不超过64k,我建议使用VARCHAR。如果Notes的内容永远不会超过1000个字符,请使用VARCHAR(1000)。