2011-10-24 53 views
16

我现在有这个模式:MySQL查询性能的两难境地:枚举VS表

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是一种好的做法吗?

感谢

+1

如果枚举列表将被更改,表格会很好。这只是一个简单的插入/更新查询。枚举需要一个更改表。 –

+0

查找类型的有符号整数(4字节)看起来有点过分 - 那么unsigned tinyints怎么样? –

+0

我应该使用unsigned int?我有超过200,000个用户 – Tech4Wilco

回答

19

就我个人而言,我认为应该使用int数据类型,并且应该在另一个层中完成该数据的枚举。

表定义是一个糟糕的地方来存储您的枚举值的色域。这很难轻松实现,并且让应用程序能够修改表定义是一个安全问题(可能)。相反,我会建议使用INT类型,然后在您的软件中创建一个与下面的数据库进行交互的模型,以提供ENUM的外观。通过这种设计选择,切换数据库软件非常简单,您无需为生产应用程序授予“ALTER TABLE”特权,并且扩展enum也很容易。另外,那么你就减少了程序需要从ENUM进行翻译的次数 - > integer - 它可以在编译时完成,而不是每个数据库的SQL请求。

+0

所以你将在一个单独的文件中为这些选项提供一个文件,并将它们用作定义或其他东西,例如:define('USER_ACCESS_ADMIN',1);? – Tech4Wilco

+0

是的,这就是我会做的 –

+0

感谢您的信息 – Tech4Wilco

1

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

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

+0

向enum添加条目实际上并不会强制重建表,因此它比您想象的更灵活。 – Johan

+0

我知道,当您必须修改information_schema.columns中的条目以保持ENUM列表处于最新状态时,维护它会稍微痛苦一点。 – Crontab

+0

这是一个简单的'alter table change column'语句,不需要在information_schema中搞乱。 – Johan