数据库优化建议

时间:2011-02-24 12:57:17

标签: mysql database database-design data-structures

我有一张叫做会员的桌子。我正在寻求建议如何改进它。

  • id:这是用户ID(唯一)(自动增量)(已编入索引)
  • 状态:可以包含“已激活”,“暂停”,“验证”,“删除”
  • admin:这只包含0或1(如果是或不是管理员)
  • suspended_note:如果会员帐户被暂停,我可以添加备注,这样当他们尝试登录时,他们会看到该备注。
  • failed_login_count:从0到4基本上是1位数,计数登录失败
  • last_visited:他们上次访问网站时的unix时间戳; (注销时更新)(我通过php with time())
  • 用户名:可以包含3到15个字符(唯一且已编入索引)
  • first_name:只能包含字母,长度为3到40个字符
  • last_name:只能包含字母,长度为2到50个字符
  • 电子邮件:可以包含电子邮件地址(我使用php电子邮件过滤器检查是否有效)
  • 密码:长度可以包含6到10个字符并且经过哈希处理,并且在数据库中包含固定长度的40个字符一次哈希
  • date_time:unix timestamp(我通过php with time()来做这个)。用户登录时
  • ip:注册/登录时的成员IP
  • activationkey:我使用md5和salt创建一个唯一的激活密钥;长度总是32个字符
  • 性别:空白或男/女,别无其他。
  • websiteurl:可以添加他们的网站网址;
  • msn:可以包含msn电子邮件地址(使用正则表达式来匹配)
  • 目标:目标昵称(使用正则表达式匹配此)
  • yim:yim nickname(使用正则表达式来匹配)
  • twitter:twitter用户名(使用正则表达式来匹配)

suspended_note; first_name; last_name; date_time; ip; gender; websiteurl; msn; aim; yim; twitter可以为null,因为在注册时只需要用户名,电子邮件和密码,因此这些字段在填写之前将为空(它们基本上是可选的而不是必需的)除了在注册/登录时采用的ip

有人能根据我提供的信息告诉我如何更有效地改进和改变这张表吗?我会说我可以改进它,因为我倾向于在大多数情况下使用varchar,并希望从中获得最佳性能。

我倾向于做很多选择并将用户数据存储在会话中,以避免每次都要查询数据库。用户名是唯一的,索引像id一样,因为我的大多数选择比较都有用户名,我的查询中有LIMIT 1。

更新

我想问一下我是否更改为enum例如如何在php中为enum执行select和compare查询?我确实在线查看,但找不到任何使用枚举的示例查询。另外,如果我将date_time更改为例如timestamp,我还是在php中使用time()将unix时间戳插入date_time列数据库吗?

我问的原因是我在线阅读一个教程,说明查询,选择,更新等行时MySQL会自动更新该行的时间戳;这是真的,因为我宁愿在时间戳字段中使用php time()插入时间戳。我已经将date time()用于date_time但是当前使用varchar而不是timestamp。

加上服务器时间在美国和php.ini我将它设置为英国时间,但我想mysql会将它存储在服务器上的时间,这在英国时间我想要它们再次没有好处。

4 个答案:

答案 0 :(得分:2)

一些提示:

  • 您的状态应该是连接到查询或枚举的int。
  • ditto for gender
  • 您可以使用char代替varchar。关于这方面有很多讨论,但虽然varchar确实帮助你减少了规模,但这在大多数时候都不是一个大问题。 char可以更快。这虽然很棘手。
  • 将您的date_time保密为timestamp。有
  • 的数据类型
  • ditto for last_visited
  • 你的ip领域看起来有点长。
  • int(5)可以容纳太多。因此,如果您的失败计数是最多4,那么您不需要那么大的数字! tinyint可以保留127个签名,或255个未签名。

评论中的注释:

  

你可能会将一些标准化   fields:经常更新的字段,例如   failed_login_count,ip,last_visited   可能在另一张桌子里。这条路   你的成员表本身没有   经常更改,可以在缓存中

我同意这一点:)

编辑:新问题后的一些更新。

  

示例如何在php中为enum执行select和compare查询?

您可以将其与值进行比较,就好像它是一个字符串一样。唯一的区别是插入或更新时,您只能使用给定值。只需使用

SELECT * FROM table WHERE table.enum = "yourEnumOption"
  

将date_time更改为例如timestamp我还在php中使用time()将unix时间戳插入date_time列数据库吗?

你可以在mysql中使用now()吗? (这只是从头部开始,可能会有一个小错误,但是:

INSERT INTO table (yourTime) VALUES (NOW());
  

我问的原因是我在线阅读一个教程,说明查询,选择,更新等行时MySQL会自动更新该行的时间戳;这是真的,因为我宁愿在时间戳字段中使用php time()插入时间戳。我已经将date time()用于date_time但是当前使用varchar而不是timestamp。

你可以使用php时间。时间戳不会自动更新,请参阅手册(http://dev.mysql.com/doc/refman/5.0/en/timestamp.html):您将在定义中使用以下内容:

CREATE TABLE t (
ts1 TIMESTAMP DEFAULT 0,
ts2 TIMESTAMP DEFAULT CURRENT_TIMESTAMP
              ON UPDATE CURRENT_TIMESTAMP)

答案 1 :(得分:2)

首先,您应该使用mysql的内置字段类型:

  • 状态为ENUM('已激活','已暂停','已验证','已删除');
  • 性别是ENUM('男性','女性','未知')
  • last_visited是TIMESTAMP
  • suspended_note是TEXT
  • 登录失败的计数是TINYINT(1),因为你不会有10000次登录失败 - INT(5)
  • date_time是DATETIME或TIMESTAMP

    1. 在用户名和密码上添加一个索引(合并),以便登录更快
    2. 索引,唯一的电子邮件,因为您将通过它查询来检索pwds并且它应该是唯一的

此外,您可能希望规范化此表并将suspended_note,网站,IP,目标等分隔到名为profile的单独表中。这种方式登录,会话更新,pwd检索是在一个小得多的表中运行的查询,并且只在您需要拥有配置文件/成员页面等数据的页面中选择其余数据。

然而,这往往会有很大差异,具体取决于您的应用如何被考虑,但通常是更好的规范化做法。

  

你可能会更加正常化   并有一个user_stats表:   经常更新的字段,例如   failed_login_count,ip,last_visited   可能在另一张桌子里。这条路   你的成员表本身没有   经常更改,可以在缓存中。 -   Konerak 1小时前

VARCHAR很好但是当你知道激活密钥总是之类的东西的大小是32然后使用CHAR(32)

答案 2 :(得分:0)

首先是基础......

IP应存储为无符号INT,您可以使用INET_ATON和INET_NTOA来检索和存储IP。

状态可以是enum或tinyint 1/0。

对于上次访问,您可以使用mysql函数UNIX_TIMESTAMP插入一个unix时间戳(将其存储在时间戳列中)。要检索日期,您将使用FROM_UNIXTIME函数。

大多数答案都涉及使用Enum的基础知识。但是,如果您通过该字段进行大量查询,则使用1表示男性,2表示女性可以加速您的应用程序,因为数字字段可能比字母数字字段更快。你应该测试一下。

其次,我们需要知道你如何使用该表。您的应用如何查询表格?你的索引在哪里?你在使用MyISAM吗? InnoDB的?我的大部分建议都是基于你的应用程序如何击中表格。该表也很宽,所以我会像其他人指出的那样对其进行标准化。

答案 3 :(得分:-1)

  • admin可以是bit
  • 类型
  • 激活密钥可以更小