A resposta de @Alden Quimby está correta até onde vai, mas há mais na história, porque o MySQL apenas tentará para escolher o índice ideal, e sua capacidade de fazer essa determinação é limitada devido à maneira como os índices de texto completo interagem com o otimizador.
O que realmente acontece é isso:
Se o user_id especificado existir em 0 ou 1 linhas correspondentes na tabela, o otimizador perceberá isso e escolherá user_id como o índice para essa consulta. Execução rápida.
Caso contrário, o otimizador escolherá o índice de texto completo, filtrando cada linha correspondente ao índice de texto completo para eliminar linhas que não contenham um user_id que corresponda à cláusula WHERE. Não tão rápido.
Portanto, não é realmente o caminho "ótimo". É mais como texto completo, com uma ótima otimização para evitar a pesquisa de texto completo sob a condição de que sabemos que não temos quase nada de interesse na tabela.
A razão disso é que um índice de texto completo não fornece nenhuma estatística significativa de volta ao otimizador. Ele apenas diz "sim, acho que essa consulta provavelmente deve exigir que eu verifique apenas 1 linha" ... o que, é claro, agrada muito ao otimizador, então o índice de texto completo ganha o lance pelo menor custo, a menos que o índice com o inteiro valor também vem em comparativamente baixo ou inferior.
Ainda assim, isso não significa que eu não tentaria dessa maneira primeiro.
Há outra opção, que funcionaria melhor com consultas de texto completo
IN BOOLEAN MODE
e isso é criar outra coluna que você preencheria com algo como CONCAT('user_id_',user_id) ou algo semelhante e, em seguida, declarar um índice de texto completo de 2 colunas. filter_string VARCHAR(48) # populated with CONCAT('user_id_',user_id);
....
FULLTEXT KEY (message,filter_string)
Em seguida, especifique tudo na consulta.
SELECT ...
WHERE user_id = 500 AND
MATCH (message,filter_string) AGAINST ('+kittens +puppies +user_id_500' IN BOOLEAN MODE);
Agora, o índice de texto completo será responsável por corresponder apenas às linhas em que gatinhos, cachorrinhos e "user_id_500" aparecem no índice de texto completo combinado das duas colunas, mas você ainda deseja ter o filtro de número inteiro lá também para garantir que o os resultados finais são limitados apesar de qualquer aparência aleatória de "user_id_500" na mensagem.