【问题标题】:MySQL query performance dilemma: enum vs tablesMySQL 查询性能困境:枚举与表
【发布时间】:2011-10-24 17:41:51
【问题描述】:

我目前有这个架构:

CREATE TABLE `users` (
  `users_id` int(11) NOT NULL AUTO_INCREMENT,
  `users_name` varchar(50),
  `users_lastname` varchar(50),
  `users_dob` date,
  `users_type` int(11) NOT NULL default 0,
  `users_access` int(11) NOT NULL default 0,
  `users_level` int(11) NOT NULL default 0,
  /* etc...*/
  PRIMARY KEY (`users_id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;

CREATE TABLE `users_types` (
  `types_id` int(11) NOT NULL AUTO_INCREMENT,
  `types_name` varchar(50),
  PRIMARY KEY (`types_id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;

/* etc..*/

查询:

SELECT
    types_name AS user_type, 
    /* all other fields*/
    users.*
    FROM users
    INNER JOIN users_types ON (users.users_type=types_id);
    /* INNER JOIN for all other tables*/
/* Rest of query */

我的新解决方案:

CREATE TABLE `users` (
  `users_id` int(11) NOT NULL AUTO_INCREMENT,
  `users_name` varchar(50),
  `users_lastname` varchar(50),
  `users_dob` date,
  `users_type` ENUM('type1', 'type2', 'type3'),
  `users_access` ENUM('access1', 'access2', 'access3'),
  `users_level` ENUM('level1', 'level2', 'level3'),
  /* etc...*/
  PRIMARY KEY (`users_id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;

查询:

SELECT
    *
    FROM users

据我所知,使用 ENUM 非常简单,并且执行速度非常快。

  1. 我说的对吗? MySQL 引擎处理 ENUM 类型字段会比处理 LEFT JOIN 更快吗?
  2. 使用 ENUM 是一种好习惯吗?

谢谢

【问题讨论】:

  • 如果枚举列表将被更改,表是好的。这只是一个简单的插入/更新查询。枚举需要一个变更表。
  • 用于查找类型的有符号整数(4 字节)似乎有点过分 - 无符号 tinyints 怎么样?
  • 我应该使用无符号整数吗?我有超过 200,000 个用户

标签: mysql performance enums


【解决方案1】:

我个人认为应该使用 int 数据类型,并且该数据的 ENUM 化应该在另一层中完成。

表定义是存储枚举值范围的糟糕地方。这很难轻易解决,并且让您的应用程序有权修改表定义是一个安全问题(可能)。

相反,我建议使用 INT 类型,然后在您的软件中创建一个与下面的数据库交互的模型,以呈现 ENUM 的外观。

通过这种设计选择,切换数据库软件是微不足道的,您不需要为您的生产应用授予“ALTER TABLE”权限,并且扩展您的枚举很容易。此外,您还可以减少程序需要从 ENUM -> 整数进行转换的次数——它可以在编译时完成,而不是在每个数据库 SQL 请求中完成。

【讨论】:

  • 因此您将在单独的文件中为这些选项提供一个文件,并将它们用作定义或其他内容,例如:define('USER_ACCESS_ADMIN', 1);?
【解决方案2】:

1) 是的,它会更快,因为 ENUM 数据类型在表本身中被索引(即无需为每条记录读取另一个表)

2) 可以,只要您不想在任何其他表中使用这些字段。一旦您想在多个表中使用给定字段,您应该为该字段创建一个单独的查找表。此外,如果您希望该字段具有用户可定义的值(并且不需要他们直接修改数据库来更改它们),您应该使用单独的表。

【讨论】:

  • 向枚举添加条目实际上并不强制重建表,因此它比您想象的更灵活。
  • 我知道,当您必须修改 information_schema.columns 中的条目以使您的 ENUM 列表保持最新时,维护它只是有点痛苦。
  • 这是一个简单的alter table change column 语句,不需要在 information_schema 中搞乱。
  • 正确,如果您希望应用程序的 MySQL 用户拥有可以正常工作的权限。不过,并不是每个人都希望应用程序用户拥有这些权限。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-12-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多