Potresti creare una "vista materializzata".http://en.wikipedia.org/wiki/Materialized_view
fondamentalmente una tabella che è i risultati di JOIN e crea un indice di testo completo su quello.
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)
È quindi possibile eseguire query su quella tabella invece..
SELECT * FROM materialized WHERE MATCH(user_name,department_name) AGAINST('test' IN BOOLEAN MODE)
ma...
Dovrai aggiornare la tabella periodicamente (o quando le tabelle sottostanti si aggiornano) - il modo più semplice è semplicemente DROP
e ricrea - Oppure puoi usare TRUNCATE
quindi INSERT INTO ... SELECT ... FROM ...
formato.
(schemi più elaborati implicano attivatori per mantenere aggiornata la "vista" o persino guardare il binlog e riprodurre gli aggiornamenti rispetto alla "vista")