Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

mysql:use SET ou muitas colunas?


Parece que você está preocupado principalmente com o desempenho.

Algumas pessoas sugeriram dividir em 3 tabelas (tabela de categorias mais uma tabela de referência cruzada simples ou uma maneira mais sofisticada de modelar a hierarquia da árvore, como conjunto aninhado ou caminho materializado), que foi a primeira coisa que pensei quando li sua pergunta .

Com índices, uma abordagem totalmente normalizada como essa (que adiciona dois JOINs) ainda terá um desempenho de leitura "muito bom". Um problema é que um INSERT ou UPDATE para um evento agora também pode incluir um ou mais INSERT/UPDATE/DELETEs para a tabela de referência cruzada, o que no MyISAM significa que a tabela de referência cruzada está bloqueada e no InnoDB significa que as linhas estão bloqueadas, portanto, se seu banco de dados estiver ocupado com um número significativo de gravações, você terá problemas de contenção maiores do que se apenas as linhas do evento estivessem bloqueadas.

Pessoalmente, eu experimentaria essa abordagem totalmente normalizada antes de otimizar. Mas, suponho que você saiba o que está fazendo, que suas suposições estão corretas (categorias nunca mudam) e você tem um padrão de uso (muitas gravações) que exige uma estrutura plana e menos normalizada. Isso é totalmente bom e faz parte do que é o NoSQL.

SET vs. "muitas colunas"


Então, quanto à sua pergunta real "SET vs. muitas colunas", posso dizer que trabalhei com duas empresas com engenheiros inteligentes (cujos produtos eram aplicativos web de CRM ... um era na verdade gerenciamento de eventos), e ambos usou a abordagem "muitas colunas" para esse tipo de conjunto de dados estáticos.

Meu conselho seria pensar em todas as consultas que você fará nesta tabela (ponderadas por sua frequência) e como os índices funcionariam.

Primeiro, com a abordagem "muitas colunas", você precisará de índices em cada uma dessas colunas para poder fazer SELECT FROM events WHERE CategoryX = TRUE . Com os índices, essa é uma consulta super-rápida.

Contra com SET, você deve usar bit a bit AND (&), LIKE ou FIND_IN_SET() para fazer esta consulta. Isso significa que a consulta não pode usar um índice e deve fazer uma pesquisa linear de todas as linhas (você pode usar EXPLAIN para verificar isso). Consulta lenta!

Essa é a principal razão pela qual SET é uma má ideia - seu índice só é útil se você estiver selecionando por grupos exatos de categorias. SET funciona muito bem se você estiver selecionando categorias por evento, mas não o contrário.

O principal problema com a abordagem "muitas colunas" menos normalizada (versus a totalmente normalizada) é que ela não é dimensionada. Se você tem 5 categorias e elas nunca mudam, tudo bem, mas se você tem 500 e está mudando, é um grande problema. Em seu cenário, com cerca de 30 que nunca mudam, o principal problema é que há um índice em cada coluna, portanto, se você estiver fazendo gravações frequentes, essas consultas ficarão mais lentas devido ao número de índices que precisam ser atualizados. Se você escolher essa abordagem, talvez queira verificar o log de consultas lentas do MySQL para certificar-se de que não há consultas lentas discrepantes devido à contenção em horários de pico do dia.

No seu caso, se o seu é um aplicativo da Web típico de leitura pesada, acho que usar a abordagem "muitas colunas" (como os dois produtos de CRM fizeram, pelo mesmo motivo) provavelmente é sensato. É definitivamente mais rápido que SET para essa consulta SELECT.

TL;DR Não use SET porque a consulta "selecionar eventos por categoria" será lenta.