Se você aderir ao Zero, One ou Many princípio, pelo qual não existe tal coisa, um deles, ou um número ilimitado, você sempre construiria tabelas devidamente normalizadas para rastrear coisas assim.
Por exemplo, um esquema possível:
CREATE TABLE user_attributes (
id INT PRIMARY KEY NOT NULL AUTO_INCREMENT,
user_id INT NOT NULL,
attribute_name VARCHAR(255) NOT NULL,
attribute_value VARCHAR(255),
UNIQUE INDEX index_user_attributes_name(user_id, attribute_name)
);
Este é o padrão básico de armazenamento de valores-chave em que você pode ter muitos atributos por usuário.
Embora os requisitos de armazenamento para isso sejam maiores do que um arranjo de colunas fixas com nomes perpetuamente frustrantes como
attribute1
, o custo é pequeno o suficiente na era dos discos rígidos de terabyte e raramente é um problema. Geralmente você cria uma única tabela para esses dados até que o tempo de inserção se torne um problema. Contanto que suas inserções sejam rápidas, eu não me preocuparia com isso. Nesse ponto, você deve considerar uma fragmentação estratégia para dividir esses dados em várias tabelas com um esquema idêntico, mas somente se for necessário.
Eu imagino que seria no estágio de ~ 10-50 milhões de linhas, mas poderia ser maior se a quantidade de atividade de inserção nesta tabela for relativamente baixa.
Não se esqueça de que a melhor maneira de otimizar a atividade de leitura é usar um cache:a consulta de banco de dados mais rápida é aquela que você não faz. Para esse tipo de coisa, você geralmente emprega algo como memcached para armazenar os resultados de buscas anteriores e você invalidaria isso em uma gravação.
Como sempre, avalie qualquer esquema proposto na produção escala.