Você pode criar uma 'visualização materializada'.http://en.wikipedia.org/wiki/Materialized_view
basicamente uma tabela que é o resultado do JOIN e cria um índice de texto completo sobre isso.
CREATE TABLE materialized (FULLTEXT idx (user_name,department_name))
SELECT u.id,user_name,department_name
FROM users u INNER JOIN departments d ON (d.id = dept_id)
Em seguida, você pode executar consultas nessa tabela.
SELECT * FROM materialized WHERE MATCH(user_name,department_name) AGAINST('test' IN BOOLEAN MODE)
mas...
Você precisará atualizar a tabela periodicamente (ou quando as tabelas subjacentes forem atualizadas) - o mais fácil é apenas
DROP
e recriar - Ou você pode usar TRUNCATE
então INSERT INTO ... SELECT ... FROM ...
formato. (esquemas mais elaborados envolvem gatilhos para manter a 'view' atualizada, ou até mesmo assistir o binlog, e repetir as atualizações na 'view')