Ist das Aufteilen einer Benutzertabelle zu Authentifizierungszwecken eine gute Idee?

8

Angenommen, ich habe eine Benutzertabelle auf meiner Site, in der sich ungefähr 2-3 Millionen Benutzer (Datensätze) in der Tabelle befinden.

Um meinen Anmeldevorgang zu beschleunigen, ist es ein guter Ansatz, meine Benutzertabelle zu teilen, eine für ihre Informationen und eine für ihre Anmeldung.

Wenn wir eine Abfrage ähnlich der folgenden aus einer Tabelle ausführen können:

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

Ist es notwendig, es zu teilen, und beschleunigt dies den Anmeldevorgang meiner Site?

ALH
quelle
1
Fügen Sie dies nur als Kommentar hinzu, da dies keine direkte Antwort auf Ihre Frage ist. Möglicherweise tun Sie dies über Ihre Beispielabfrage hinaus, aber es ist sehr, sehr schlecht, die tatsächlichen Kennwörter in Ihrer Datenbank zu speichern. Sie möchten sie als has speichern und dann abfragen wie where password_hash = hash ($ userEnteredPassword)
atxdba
@atxdba Ich habe sie tatsächlich gehasht, aber hier habe ich nur ein Beispiel gegeben.
ALH

Antworten:

10

IMHO Sie müssen es nicht physisch aufteilen. Es wäre jedoch schön, es zwischenzuspeichern.

Wenn die usersTabelle die MyISAM Storage Engine verwendet, haben Sie einen schönen Vorteil.

Da MyISAM nur Indizes zwischenspeichert, können Sie zwei Dinge tun

  • Sie können einen benutzerdefinierten Schlüsselcache erstellen, um den MyISAM-Index nur für die usersTabelle zu laden
  • Sie können den Benutzernamen und das Kennwort indizieren, um zu erzwingen, dass die Abfrage nur diesen benutzerdefinierten Schlüsselcache erreicht

Stellen Sie sicher, dass die folgenden Indizes für vorhanden sind users

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

Es gibt zwei (2) Hauptgründe für die beiden Indizes

GRUND für Index # 1

Der Index username_ndxverhindert, dass ein Benutzername mehrere Kennwörter hat, und verhindert, dass mehrere Benutzer denselben Namen haben

GRUND für Index # 2

Der Index username_password_ndxbietet einen Deckungsindex . Daher sucht Ihre Abfrage nur den Benutzernamen und das Kennwort im benutzerdefinierten MyISAM-Cache, anstatt die Tabelle zu überprüfen.

Weitere Links zu den Grundsätzen der Indexabdeckung

Als Nächstes müssen Sie diesen benutzerdefinierten Schlüsselcache erstellen. Hier sind die Befehle zum Erstellen eines 8-MB-Schlüsselcaches und zum Laden dieses dedizierten Schlüsselcaches (Beispiel: Wenn die Tabelle vorhanden ist 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;

Sie sollten diese drei Zeilen in die Datei /var/lib/mysql/startup.sql einfügen

Fügen Sie dies zu /etc/my.cnf hinzu

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

Dadurch wird der Cache jedes Mal geladen, wenn MySQL gestartet wird

Versuche es !!!

UPDATE 30.12.2011 17:25 EDT

Wenn Sie die genaue Größe zum Festlegen des Caches erhalten möchten, verwenden Sie die folgende Abfrage:

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

UPDATE 30.12.2011 23:21 EDT

Hier ist eine Methode, die auf InnoDB basiert

Sie benötigen noch die Indizes

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

Sie müssen sicherstellen, dass im InnoDB-Pufferpool die Benutzernamen und Kennwörter verfügbar sind. Möglicherweise müssen Sie beim Start von MySQL einen vollständigen Index-Scan durchführen:

Schritt 1) ​​Erstellen Sie ReadUserPass.sql

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

Schritt 2) Fügen Sie dieses Skript zu /etc/my.cnf hinzu

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

Schritt 3) Führen Sie einen der folgenden Schritte aus

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

Da sich beide Spalten (Benutzername und Kennwort) in der befinden username_password_ndx, werden alle Indexseiten, aus denen dieser Index besteht, erneut in den InnoDB-Pufferpool geladen. Dies ist erforderlich, da die Indexseiten möglicherweise gelöscht werden. Um dies zu minimieren, erhöhen Sie die Größe des Pufferpools und starten Sie mysql neu (einmalig).

RolandoMySQLDBA
quelle
Eigentlich verwende ich die InnoDB-Speicher-Engine, aber ich denke, der Cache-Prozess wäre in Ordnung, nicht wahr @RolandoMySQLDBA?
ALH
Nein. Die Schritte in meiner Antwort sind nur MyISAM.
RolandoMySQLDBA
Wenn die usersTabelle an Transaktionen beteiligt ist, muss ich eine andere Antwort einreichen, die ausschließlich auf InnoDB basiert.
RolandoMySQLDBA
Entschuldigung, das habe ich nicht erwähnt, ich wusste nicht, dass sie unterschiedliche Ansätze haben würden!
ALH
Ich habe basierend auf MyISAM geantwortet, weil ich wollte, dass die Benutzertabelle in einem eigenen Schlüsselpuffer zwischengespeichert wird.
RolandoMySQLDBA
5

Eine Tabelle mit ein paar Millionen Zeilen sollte nicht aufgeteilt werden müssen. Die Leistungsoptimierung sollte über Indizes erfolgen. In MySpace waren Hunderte Millionen Konten in einer einzigen Tabelle aufgeführt, und die Leistung in dieser Tabelle war in Ordnung. (Ich war ein DBA für MySpace auf dem Höhepunkt ihrer Nutzung.) Die Tabelle war in diesem Fall wahrscheinlich 80-90 Byte breit (vielleicht etwas mehr).

mrdenny
quelle
Wie war die RAM-Größe?
Chibueze Opata
3

Haben Sie tatsächlich 2 Millionen Benutzer? Sofern Sie dieses Problem nicht bereits haben oder sicher sind, dass Sie es tun werden, optimieren Sie weit im Voraus. Fügen Sie einen zusammengesetzten Index für Anmelde- und Kennwortfelder hinzu und fertig. Optimieren Sie nur, wenn Sie wissen, dass Sie tatsächlich ein Problem zu lösen haben. Ich bin sicher, Sie haben größere Probleme zu lösen.

Aaron Brown
quelle
1
Was meinst du mit "du bist sicher, dass ich größere Probleme zu lösen habe"?
ALH
1
Es ist nicht sinnvoll, Probleme zu lösen, wenn wir wissen, dass wir in naher Zukunft auf viele Probleme stoßen werden. Diese Fehlerbehebung bereitet Kopfschmerzen, wenn die Tabelle viele Daten enthält! -1 für dich.
ALH
2
Mein Punkt ist zweifach ... nicht optimieren, bevor Sie müssen & 2 Millionen Datensätze sind nicht sehr viele. Ein Index wird reichlich sein.
Aaron Brown
2

Wenn Sie MySQL 5.1 und höher verwenden, können Sie versuchen , Ihre Tabelle zu partitionieren .
Bei Ihrer Frage, ob der Anmeldevorgang beschleunigt wird, hängt es davon ab, wie der Rest des Anmeldevorgangs aussieht (wenn Ihre Abfrage beispielsweise jetzt 0,05 Sekunden dauert und der Rest des Codes 20 Sekunden dauert, würde ich lieber erneut denke die ganze Routine ...).
Vergessen Sie auch nicht, unabhängig von der Verwendung von Partitionen Indizes hinzuzufügen, wie RolandoMySQLDBA hervorhob .

a1ex07
quelle
Guter Aufruf, um die tatsächliche Ursache eines Leistungsproblems vor der Optimierung zu ermitteln. Es ist oft nicht dort, wo wir denken. Evidenzbasiertes Tuning ist der richtige Weg!
Stuart Woodward