假设我的站点中有一个用户表,该表中大约有2-3百万个用户(记录)。
为了加快我的登录过程,这是拆分用户表的好方法,一个用户表用于提供信息,另一个用于用户登录。
如果我们可以从一个表中运行类似于以下查询的查询:
select username,password from users where username=`test` AND password=****
是否有必要将其拆分,这会加快我的网站的登录过程吗?
假设我的站点中有一个用户表,该表中大约有2-3百万个用户(记录)。
为了加快我的登录过程,这是拆分用户表的好方法,一个用户表用于提供信息,另一个用于用户登录。
如果我们可以从一个表中运行类似于以下查询的查询:
select username,password from users where username=`test` AND password=****
是否有必要将其拆分,这会加快我的网站的登录过程吗?
Answers:
恕我直言,您无需将其物理拆分。但是,缓存它会很好。
如果该users
表使用MyISAM存储引擎,则将具有很好的优势。
由于MyISAM仅缓存索引,因此您可以做两件事
users
表的MyISAM索引确保以下索引存在 users
ALTER TABLE users ADD UNIQUE INDEX username_ndx (username);
ALTER TABLE users ADD UNIQUE INDEX username_password_ndx (username,password);
这两个索引有两个主要原因(2)
该索引username_ndx
可防止一个用户名具有多个密码,并防止多个具有相同名称的用户
该索引username_password_ndx
提供覆盖索引。因此,您的查询将仅在自定义MyISAM缓存中查找用户名和密码,而不是检查表。
有关覆盖索引原理的更多链接
下一步是实际创建该自定义密钥缓存。以下是用于创建8MB密钥缓存并加载该专用密钥缓存的命令(示例:如果表为mydb.users
):
SET GLOBAL authentication_cache.key_buffer_size = 1024 * 1024 * 8;
CACHE INDEX mydb.users IN authentication_cache;
LOAD INDEX INTO CACHE mydb.users;
您应该将这三行放在文件/var/lib/mysql/startup.sql中
将此添加到/etc/my.cnf
[mysqld]
init-file=/var/lib/mysql/startup.sql
这将在每次启动mysql时加载缓存
试试看 !!!
如果您想获得确切的大小来设置缓存,请使用以下查询:
SELECT CONCAT('1024 * 1024 * ',ROUND(index_length/power(1024,2))) RecommendedCacheSize
FROM information_schema.tables WHERE table_name='users';
这是一个基于InnoDB的方法
您仍然需要索引
ALTER TABLE users ADD UNIQUE INDEX username_ndx (username);
ALTER TABLE users ADD UNIQUE INDEX username_password_ndx (username,password);
您必须确保InnoDB缓冲池具有可用的用户名和密码。您可能必须诉诸于在mysql启动时进行完整的索引扫描:
步骤1)创建ReadUserPass.sql
echo "select username,password from users;" > /var/lib/mysql/ReadUserPass.sql
第2步)将该脚本添加到/etc/my.cnf
[mysqld]
init-file=/var/lib/mysql/ReadUserPass.sql
步骤3)执行以下操作之一
$ service mysql restart
mysql> source /var/lib/mysql/ReadUserPass.sql
因为这两个列(用户名和密码)都位于中username_password_ndx
,所以构成该索引的所有索引页都被重新加载到InnoDB缓冲池中。这是必要的,因为有可能冲走索引页。为了最大程度地减少这种情况,请增加缓冲池大小并重新启动mysql(一次)。
users
表涉及事务,那么我需要仅基于InnoDB提交另一个答案。
无需拆分几百万行的表。性能调整应该通过索引来完成。MySpace在一个表中列出了数亿个帐户,该表的性能很好。(在使用它们时,我曾是MySpace的DBA。)在这种情况下,表的宽度可能为80-90字节(可能更多)。
如果使用Mysql 5.1和更高版本,则可以尝试对表进行分区。
关于您是否会加快登录过程的问题,这取决于其余登录过程的外观(例如,如果您的查询现在需要0.05秒,而其余代码需要20秒,我宁愿重新考虑整个程序...)。
另外,无论使用分区如何,都不要忘记像RolandoMySQLDBA所指出的那样添加索引。