私のサイトにユーザーテーブルがあり、テーブルに約200万から300万のユーザー(レコード)がいるとします。
ログインプロセスを高速化するために、1つは情報用に、もう1つはログイン用に、ユーザーテーブルを分割することをお勧めします。
次のようなクエリを1つのテーブルから実行できる場合:
select username,password from users where username=`test` AND password=****
それを分割する必要はありますか?これは私のサイトのログインプロセスをスピードアップしますか?
IMHO物理的に分割する必要はありません。それでも、それをキャッシュしておくといいでしょう。
users
テーブルがMyISAMストレージエンジンを使用している場合、すばらしい利点があります。
MyISAMはインデックスをキャッシュするだけなので、2つのことを行うことができます
users
テーブルのみのMyISAMインデックスをロードするためだけにカスタムキーキャッシュを作成できます次のインデックスがusers
に存在することを確認してください
ALTER TABLE users ADD UNIQUE INDEX username_ndx (username);
ALTER TABLE users ADD UNIQUE INDEX username_password_ndx (username,password);
2つのインデックスには2つの主な理由があります。
インデックスusername_ndx
は、ユーザー名が複数のパスワードを持つことを防ぎ、同じ名前の複数のユーザーを防ぐ
インデックスusername_password_ndx
は covering index を提供します。したがって、クエリは、テーブルをチェックするのではなく、カスタム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;
これらの3行をファイル/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を再起動します(1回限り)。
数百万行のテーブルを分割する必要はありません。パフォーマンスのチューニングは、インデックスを介して行う必要があります。 MySpaceでは、1つのテーブルに数億のアカウントがリストされており、そのテーブルでのパフォーマンスは問題ありませんでした。 (私はMySpaceのDBAでしたが、使用量が最も多かったです。)その場合のテーブルの幅はおそらく80〜90バイト(おそらくもう少し)でした。
実際に200万人のユーザーがいますか?すでにこの問題が発生しているか、発生することが確実でない限り、事前に最適化しています。ログインフィールドとパスワードフィールドに複合インデックスを追加し、それで完了します。実際に解決する問題があることがわかっている場合を除いて、最適化しないでください。あなたが解決すべきより大きな問題があると私は確信しています。
Mysql 5.1以降を使用している場合は、 partitioning テーブルを試すことができます。
ログインプロセスを高速化するかどうかについてのあなたの質問のように、それは残りのログイン手順がどのように見えるかに依存します(たとえば、クエリが0.05秒かかり、残りのコードが20秒かかる場合、むしろルーチン全体を考え直してください...)。
また、パーティションの使用に関係なく、RolandoMySQLDBAが指摘したように、インデックスを追加することを忘れないでください。