É uma boa ideia dividir uma tabela de 'usuários' para fins de autenticação?

8

Suponha que eu tenha uma tabela de usuários no meu site na qual haja cerca de 2 a 3 milhões de usuários (registros) na tabela.

Para acelerar meu processo de login, é uma boa abordagem dividir minha tabela de usuários, uma para informações e outra para o login.

Se pudermos executar uma consulta semelhante à abaixo em uma tabela:

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

É necessário dividi-lo e isso acelera o processo de login do meu site?

ALH
fonte
11
Adicionar isso apenas como um comentário, pois não é uma resposta direta à sua pergunta. Talvez seja isso que você está fazendo além da consulta de amostra, mas é uma prática muito muito ruim armazenar as senhas reais no banco de dados. Você deseja armazená-los como um has e, em seguida, consultar como password_hash = hash ($ userEnteredPassword)
atxdba
@atxdba Na verdade, fiz um hash, mas aqui apenas dei um exemplo.
ALH

Respostas:

10

IMHO Você não precisa dividir fisicamente. No entanto, seria bom armazená-lo em cache.

Se a userstabela usar o MyISAM Storage Engine, você terá uma boa vantagem.

Como o MyISAM apenas armazena em cache índices, você pode fazer duas coisas

  • Você pode criar um cache de chaves personalizado apenas para carregar o índice MyISAM apenas para a userstabela
  • Você pode indexar o nome de usuário e a senha para forçar a consulta a atingir apenas o cache de chaves personalizado

Verifique se os seguintes índices existem para users

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

Existem dois (2) principais motivos para os dois índices

MOTIVO do índice # 1

O índice username_ndxevita que um nome de usuário tenha várias senhas e também vários usuários com o mesmo nome

MOTIVO do índice # 2

O índice username_password_ndxfornece um índice de cobertura . Portanto, sua consulta pesquisará apenas o nome de usuário e a senha no cache personalizado do MyISAM, em vez de verificar a tabela.

Mais links sobre os princípios de cobertura de índices

O próximo passo é criar esse cache de chaves personalizado. Aqui estão os comandos para criar um cache de chaves de 8 MB e carregar esse cache de chaves dedicado (exemplo: se a tabela for 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;

Você deve colocar essas três linhas no arquivo /var/lib/mysql/startup.sql

Adicione isso ao /etc/my.cnf

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

Isso carregará o cache toda vez que o mysql for iniciado

De uma chance !!!

UPDATE 2011-12-30 17:25 EDT

Se você deseja obter o tamanho exato para definir o cache, use a seguinte consulta:

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

UPDATE 2011-12-30 23:21 EDT

Aqui está um método baseado no InnoDB

Você ainda precisa dos índices

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

Você precisa garantir que o InnoDB Buffer Pool tenha nomes de usuário e senhas disponíveis. Você pode ter que recorrer a uma verificação completa do índice na inicialização do mysql:

Etapa 1) Criar ReadUserPass.sql

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

Etapa 2) Adicione esse script ao /etc/my.cnf

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

Etapa 3) Execute um dos seguintes

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

Como essas duas colunas (nome de usuário e senha) residem na username_password_ndx, todas as páginas de índice que compõem esse índice são recarregadas no InnoDB Buffer Pool. Isso é necessário porque existe a possibilidade de as páginas de índice serem liberadas. Para minimizar isso, aumente o tamanho do buffer pool e reinicie o mysql (uma vez).

RolandoMySQLDBA
fonte
Na verdade, eu uso o mecanismo de armazenamento InnoDB, mas acho que o processo de cache seria bom com ele, não é @RolandoMySQLDBA?
ALH
Não. Os passos da minha resposta são apenas MyISAM.
RolandoMySQLDBA
Se a userstabela estiver envolvida em transações, preciso enviar outra resposta baseada exclusivamente no InnoDB.
RolandoMySQLDBA
Desculpe por não ter mencionado isso, eu não sabia que eles teriam abordagens diferentes!
ALH
Respondi com base no MyISAM porque queria que a tabela de usuários fosse armazenada em cache em seu próprio buffer de chave.
RolandoMySQLDBA
5

Uma tabela de alguns milhões de linhas não precisa ser dividida. O ajuste do desempenho deve ser feito por meio de índices. O MySpace tinha centenas de milhões de contas listadas em uma única tabela e o desempenho nessa tabela foi ótimo. (Eu era um DBA do MySpace no auge de seu uso.) A tabela nesse caso tinha provavelmente 80-90 bytes de largura (talvez um pouco mais).

Mrdenny
fonte
Qual foi o tamanho da RAM?
Chibueze Opata
3

Você realmente tem 2 milhões de usuários? A menos que você já tenha esse problema ou tenha certeza de que terá, você está otimizando com bastante antecedência. Adicione um índice composto nos campos de login e senha e pronto. Não otimize, a menos que saiba que realmente tem um problema a resolver. Estou certo de que você tem problemas maiores para resolver.

Aaron Brown
fonte
11
O que você quer dizer com "você tem certeza de que tenho problemas maiores para resolver"?
ALH
11
Não faz sentido resolver problemas quando soubermos em um futuro próximo que encontraremos muitos problemas. Essa solução de problemas é uma dor de cabeça quando há muitos dados na tabela! -1 para você.
ALH
2
Meu ponto é duplo ... não otimize antes que você precise & 2 milhões de registros não são muitos. Um índice será suficiente.
Aaron Brown
2

Se você usa o Mysql 5.1 e superior, pode tentar particionar sua tabela.
Quanto à sua pergunta sobre se ele acelera o processo de login, isso depende da aparência do restante do procedimento de login (por exemplo, se sua consulta agora leva 0,05 segundos e o restante do código leva 20 segundos, eu prefiro pense toda a rotina ...).
Além disso, independentemente do uso de partições, não se esqueça de adicionar índices como RolandoMySQLDBA apontou.

a1ex07
fonte
Boa decisão para determinar a causa real de um problema de desempenho antes de otimizar. Muitas vezes não é onde pensamos que é. O ajuste baseado em evidências é o caminho a seguir!
Stuart Woodward