É 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?


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).


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).


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.


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.


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
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.