Dividere una tabella "utenti" a fini di autenticazione è una buona idea?


8

Supponiamo di avere una tabella utenti nel mio sito in cui ci sono circa 2-3 milioni di utenti (record) nella tabella.

Per accelerare il mio processo di accesso, è un buon approccio per dividere la mia tabella utente, una per le loro informazioni e una per il loro accesso.

Se possiamo eseguire una query simile a quella seguente da una tabella:

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

È necessario dividerlo e questo accelera il processo di accesso al mio sito?


1
Aggiungendo questo come solo un commento in quanto non è una risposta diretta alla tua domanda. Forse questo è ciò che stai facendo oltre la query di esempio, ma è una pessima pratica archiviare le password effettive nel database. Si desidera memorizzarli come has e quindi interrogare come dove password_hash = hash ($ userEnteredPassword)
atxdba

@atxdba Li ho effettivamente hash, ma qui ho appena fatto un esempio.
ALH,

Risposte:


10

IMHO Non è necessario suddividerlo fisicamente. Tuttavia, sarebbe bello memorizzarlo nella cache.

Se la userstabella utilizza MyISAM Storage Engine, hai un bel vantaggio.

Poiché MyISAM memorizza solo nella cache gli indici, potresti fare due cose

  • È possibile creare una cache delle chiavi personalizzata solo per caricare l'indice MyISAM userssolo per la tabella
  • È possibile indicizzare il nome utente e la password per forzare la query a colpire solo quella cache di chiavi personalizzate

Assicurarsi che esistano i seguenti indici per users

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

Esistono due (2) ragioni principali per i due indici

MOTIVO dell'indice n. 1

L'indice username_ndximpedisce a un nome utente di avere più password e impedisce a più utenti con lo stesso nome

MOTIVO dell'indice n. 2

L'indice username_password_ndxfornisce un indice di copertura . Pertanto, la query cercherà il nome utente e la password solo nella cache MyISAM personalizzata, anziché controllare la tabella.

Ulteriori collegamenti sui principi di copertura degli indici

La prossima cosa è creare effettivamente quella cache di chiavi personalizzate. Ecco i comandi per creare una cache delle chiavi da 8 MB e caricare quella cache delle chiavi dedicata (Esempio: se la tabella è 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;

Dovresti inserire queste tre righe nel file /var/lib/mysql/startup.sql

Aggiungi questo a /etc/my.cnf

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

Questo caricherà la cache ogni volta che mysql viene avviato

Provaci !!!

AGGIORNAMENTO 2011-12-30 17:25 EDT

Se desideri ottenere le dimensioni esatte per impostare la cache, utilizza la seguente query:

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

AGGIORNAMENTO 2011-12-30 23:21 EDT

Ecco un metodo basato su InnoDB

Hai ancora bisogno degli indici

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

Devi assicurarti che il pool di buffer InnoDB abbia i nomi utente e le password disponibili. Potrebbe essere necessario ricorrere a una scansione completa dell'indice all'avvio di mysql:

Passaggio 1) Creare ReadUserPass.sql

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

Passaggio 2) Aggiungi quello script a /etc/my.cnf

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

Passaggio 3) Eseguire una delle seguenti operazioni

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

Poiché entrambe queste colonne (nome utente e password) risiedono nel username_password_ndx, tutte le pagine dell'indice che compongono questo indice vengono ricaricate nel pool di buffer InnoDB. Ciò è necessario perché esiste la possibilità di svuotare le pagine dell'indice. Per ridurre al minimo ciò, aumentare le dimensioni del pool di buffer e riavviare mysql (una volta).


In realtà utilizzo il motore di archiviazione InnoDB, ma penso che il processo di cache andrebbe bene, non è vero @RolandoMySQLDBA?
ALH,

No. I passaggi nella mia risposta sono solo MyISAM.
RolandoMySQLDBA

Se la userstabella è coinvolta nelle transazioni, allora devo inviare un'altra risposta basata esclusivamente su InnoDB.
RolandoMySQLDBA

Mi dispiace non averlo menzionato, non sapevo che avrebbero approcci diversi!
ALH,

Ho risposto in base a MyISAM perché volevo che la tabella degli utenti fosse memorizzata nella cache nel proprio buffer delle chiavi.
RolandoMySQLDBA

5

Non è necessario suddividere una tabella di un paio di milioni di righe. L'ottimizzazione delle prestazioni deve essere eseguita tramite indici. MySpace aveva centinaia di milioni di account elencati in una singola tabella e le prestazioni su quella tabella andavano bene. (Ero un DBA per MySpace al culmine del loro utilizzo.) La tabella in quel caso era probabilmente larga 80-90 byte (forse un po 'di più).


Eh, com'era la dimensione della RAM?
Chibueze Opata,

3

Hai effettivamente 2 milioni di utenti? A meno che tu non abbia già questo problema o sia sicuro che lo farai, stai ottimizzando in anticipo. Aggiungi un indice composto sui campi di login e password e completa l'operazione. Non ottimizzare se non sai di avere effettivamente un problema da risolvere. Sono certo che hai problemi più grandi da risolvere.


1
Cosa intendi con "sei certo che ho problemi più grandi da risolvere"?
ALH,

1
Non ha senso risolvere i problemi quando sappiamo che nel prossimo futuro incontreremo molti problemi. Questa risoluzione dei problemi è un mal di testa quando ci sono molti dati nella tabella! -1 per te.
ALH,

2
Il mio punto è duplice ... non ottimizzare prima di dover & 2 milioni di record non sono molti. Un indice sarà abbondante.
Aaron Brown,

2

Se usi Mysql 5.1 e versioni successive, puoi provare a partizionare la tabella.
A partire dalla tua domanda se accelera il processo di accesso, dipende da come appare il resto della procedura di accesso (ad esempio, se la tua query ora richiede 0,05 secondi e il resto del codice richiede 20 secondi, preferirei ri pensa a tutta la routine ...).
Inoltre, indipendentemente dall'utilizzo delle partizioni, non dimenticare di aggiungere indici come ha sottolineato RolandoMySQLDBA .


Buona chiamata per determinare la causa effettiva di un problema di prestazioni prima dell'ottimizzazione. Spesso non è dove pensiamo che sia. La sintonizzazione basata sulle prove è la strada da percorrere!
Stuart Woodward
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.