Le fractionnement d'une table «utilisateurs» à des fins d'authentification est-il une bonne idée?


8

Supposons que mon site comporte une table d'utilisateurs dans laquelle il y a environ 2 à 3 millions d'utilisateurs (enregistrements) dans la table.

Pour accélérer mon processus de connexion, est-ce une bonne approche pour diviser ma table d'utilisateurs, une pour leurs informations et une pour leur connexion.

Si nous pouvons exécuter une requête similaire à celle ci-dessous à partir d'une table:

select username,password from users where username=`test` AND password=****

Est-il nécessaire de le diviser et cela accélère-t-il le processus de connexion de mon site?


1
Ajouter cela comme un simple commentaire car ce n'est pas une réponse directe à votre question. C'est peut-être ce que vous faites au-delà de votre exemple de requête, mais c'est une très mauvaise pratique de stocker les mots de passe réels dans votre base de données. Vous voulez les stocker en tant que has et ensuite interroger comme où password_hash = hash ($ userEnteredPassword)
atxdba

@atxdba Je les ai en fait hachés, mais ici je viens de donner un exemple.
ALH

Réponses:


10

À mon humble avis, vous n'avez pas besoin de le diviser physiquement. Pourtant, ce serait bien de le mettre en cache.

Si le userstableau utilise le moteur de stockage MyISAM, vous avez un bel avantage.

Puisque MyISAM ne met en cache que les index, vous pouvez faire deux choses

  • Vous pouvez créer un cache de clés personnalisé juste pour charger l'index MyISAM pour la userstable uniquement
  • Vous pouvez indexer le nom d'utilisateur et le mot de passe pour forcer la requête à atteindre uniquement le cache de clés personnalisé

Assurez-vous que les index suivants existent pour users

ALTER TABLE users ADD UNIQUE INDEX username_ndx (username);
ALTER TABLE users ADD UNIQUE INDEX username_password_ndx (username,password);

Il y a deux (2) raisons principales pour les deux indices

RAISON de l'index # 1

L'index username_ndxempêche un nom d'utilisateur d'avoir plusieurs mots de passe et empêche plusieurs utilisateurs portant le même nom

RAISON de l'index # 2

L'indice username_password_ndxfournit un indice de couverture . Ainsi, votre requête recherchera le nom d'utilisateur et le mot de passe dans le cache MyISAM personnalisé uniquement, au lieu de vérifier la table.

Plus de liens sur les principes de couverture des index

La prochaine étape consiste à créer ce cache de clés personnalisé. Voici les commandes pour créer un cache de clés de 8 Mo et charger ce cache de clés dédié (Exemple: si la table est 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;

Vous devez placer ces trois lignes dans le fichier /var/lib/mysql/startup.sql

Ajoutez ceci à /etc/my.cnf

[mysqld]
init-file=/var/lib/mysql/startup.sql

Cela chargera le cache à chaque démarrage de mysql

Essaie !!!

MISE À JOUR 2011-12-30 17:25 EDT

Si vous souhaitez obtenir la taille exacte pour définir le cache, utilisez la requête suivante:

SELECT CONCAT('1024 * 1024 * ',ROUND(index_length/power(1024,2))) RecommendedCacheSize
FROM information_schema.tables WHERE table_name='users';

MISE À JOUR 2011-12-30 23:21 EDT

Voici une méthode basée sur InnoDB

Vous avez toujours besoin des index

ALTER TABLE users ADD UNIQUE INDEX username_ndx (username);
ALTER TABLE users ADD UNIQUE INDEX username_password_ndx (username,password);

Vous devez vous assurer que le pool de tampons InnoDB dispose des noms d'utilisateur et des mots de passe disponibles. Vous devrez peut-être recourir à une analyse complète de l'index au démarrage de mysql:

Étape 1) Créez ReadUserPass.sql

echo "select username,password from users;" > /var/lib/mysql/ReadUserPass.sql

Étape 2) Ajoutez ce script à /etc/my.cnf

[mysqld]
init-file=/var/lib/mysql/ReadUserPass.sql

Étape 3) Effectuez l'une des opérations suivantes

  • $ service mysql restart
  • mysql> source /var/lib/mysql/ReadUserPass.sql

Étant donné que ces deux colonnes (nom d'utilisateur et mot de passe) résident dans le username_password_ndx, toutes les pages d'index constituant cet index sont rechargées dans le pool de mémoire tampon InnoDB. Cela est nécessaire car il est possible que les pages d'index soient vidées. Pour minimiser cela, augmentez la taille du pool de tampons et redémarrez mysql (une fois).


En fait, j'utilise le moteur de stockage InnoDB, mais je pense que le processus de cache lui conviendrait, n'est-ce pas @RolandoMySQLDBA?
ALH

Non. Les étapes de ma réponse sont uniquement MyISAM.
RolandoMySQLDBA

Si la userstable est impliquée dans des transactions, je dois soumettre une autre réponse basée uniquement sur InnoDB.
RolandoMySQLDBA

Désolé, je n'ai pas mentionné cela, je ne savais pas qu'ils auraient des approches différentes!
ALH

J'ai répondu sur la base de MyISAM parce que je voulais que la table des utilisateurs soit mise en cache dans son propre tampon de clé.
RolandoMySQLDBA

5

Une table de quelques millions de lignes ne devrait pas être divisée. Le réglage des performances doit être effectué via des index. MySpace avait des centaines de millions de comptes répertoriés dans une seule table et les performances sur cette table étaient très bien. (J'étais un DBA pour MySpace à la hauteur de leur utilisation.) La table dans ce cas était probablement de 80 à 90 octets de large (peut-être un peu plus).


Eh, à quoi ressemblait la taille de la RAM?
Chibueze Opata

3

Avez-vous actuellement 2 millions d'utilisateurs? Sauf si vous avez déjà ce problème ou si vous êtes certain que vous le ferez, vous optimisez à l'avance. Ajoutez un index composé sur les champs de connexion et de mot de passe et finissez-en. N'optimisez pas sauf si vous savez que vous avez réellement un problème à résoudre. Je suis certain que vous avez de plus gros problèmes à résoudre.


1
Que voulez-vous dire par "vous êtes certain que j'ai de plus gros problèmes à résoudre"?
ALH

1
Il n'est pas logique de résoudre des problèmes lorsque nous savons que dans un proche avenir, nous rencontrerons de nombreux problèmes. Ce dépannage est un casse-tête quand il y a beaucoup de données dans le tableau! -1 pour vous.
ALH

2
Mon point est double ... n'optimisez pas avant de devoir & 2 millions d'enregistrements n'est pas très nombreux. Un indice sera suffisant.
Aaron Brown

2

Si vous utilisez Mysql 5.1 et supérieur, vous pouvez essayer de partitionner votre table.
En ce qui concerne votre question sur l'accélération du processus de connexion, cela dépend de l'apparence du reste de la procédure de connexion (par exemple, si votre requête prend maintenant 0,05 seconde et le reste du code prend 20 secondes, je préfère pensez à toute la routine ...).
Aussi, indépendamment de l'utilisation de partitions, n'oubliez pas d'ajouter des index comme l' a souligné RolandoMySQLDBA .


Bon appel pour déterminer la cause réelle d'un problème de performances avant l'optimisation. Ce n'est souvent pas là où nous pensons que c'est. Le réglage basé sur des preuves est la voie à suivre!
Stuart Woodward
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.