Cosa succede
Il valore restituito da MATCH(col) AGAINST ('parole') non e' una misura di somiglianza fra 0 e 1: dipende dalla dimensione del corpus, perche' incorpora un fattore inverse document frequency calcolato sull'intera tabella. La stessa riga, con la stessa query, passa da 0 a 10,6 a 17,9 man mano che la tabella si riempie di righe che non c'entrano niente.
Perche' fa perdere tempo: e' naturale scrivere WHERE MATCH(...) AGAINST (...) > 8 per dire "solo i risultati molto simili". In sviluppo, con poche righe di prova, quella condizione non e' mai vera e il codice sembra semplicemente non funzionare; in produzione, con la tabella piena, diventa vera quasi sempre. In entrambi i casi il difetto non si manifesta come errore, ma come funzionalita' che si comporta al contrario di come sembra. Nel mio caso un rilevatore di duplicati non ha agganciato nessun doppione per un'ora prima che capissi che la soglia era il problema, e non la query.
Proposta: la documentazione dovrebbe dire a chiare lettere che il punteggio e' relativo al corpus e non confrontabile fra tabelle o nel tempo, e sconsigliare esplicitamente le soglie numeriche assolute. La soluzione pratica e' usare il full-text solo per pescare i candidati e decidere con una misura normalizzata (per esempio Jaccard sui token) calcolata a parte.
Come riprodurlo
CREATE TABLE prova_ft (id INT AUTO_INCREMENT PRIMARY KEY, testo TEXT, FULLTEXT(testo)) ENGINE=InnoDB;
INSERT INTO prova_ft (testo) VALUES ('alfa beta gamma delta');
SELECT MATCH(testo) AGAINST ('alfa beta') FROM prova_ft WHERE id=1; -- 0
INSERT INTO prova_ft (testo) SELECT 'zeta eta theta iota' FROM information_schema.columns LIMIT 200;
SELECT MATCH(testo) AGAINST ('alfa beta') FROM prova_ft WHERE id=1; -- 10.6094
INSERT INTO prova_ft (testo) SELECT 'kappa lambda mu nu xi' FROM information_schema.columns LIMIT 2000;
SELECT MATCH(testo) AGAINST ('alfa beta') FROM prova_ft WHERE id=1; -- 17.9529
Atteso
Un punteggio stabile per la stessa riga e la stessa query, oppure una documentazione che dica chiaramente che il valore e' relativo al corpus e non va usato come soglia assoluta.
Ottenuto
Lo stesso identico confronto vale 0 con una riga in tabella, 10,6094 con 201 righe e 17,9529 con 2201 righe. Nessun avviso, nessun errore: cambia solo il comportamento del codice che usa una soglia.