Mysql
 sql >> Database >  >> RDS >> Mysql

MySQL:indice composito fulltext+btree?

Usa IN BOOLEAN MODE .

L'indice delle date non è utile. Non c'è modo di combinare i due indici.

Attenzione, se un utente cerca qualcosa che appare in 30.000 righe, la query sarà lenta. Non c'è niente di semplice intorno ad esso.

Sospetto che tu abbia un TEXT colonna nella tabella? Se è così, c'è speranza. Invece di fare alla cieca SELECT * , troviamo prima gli ID e otteniamo il LIMIT applicato, poi fai il * .

SELECT a.* 
    FROM tbl AS a
    JOIN ( SELECT date, id
             FROM tbl
             WHERE MATCH(...) AGAINST (...)
             ORDER BY date DESC
             LIMIT 10 ) AS x
        USING(date, id)
    ORDER BY date DESC;

Insieme a

PRIMARY KEY(date, id),
INDEX(id),
FULLTEXT(...)

Questa formulazione e indicizzazione dovrebbero funzionare in questo modo:

  1. Usa FULLTEXT per trovare 30.000 righe, consegna il PK.
  2. Con il PK, ordina 30.000 righe per date .
  3. Scegli gli ultimi 10, fornendo date, id
  4. Torna al tavolo 10 volte usando il PK.
  5. Ordina di nuovo. (Sì, questo è necessario.)

Altro (Rispondendo a una pletora di commenti):

L'obiettivo alla base della mia riformulazione è evitare di recuperare tutti colonne di 30.000 righe. Invece, recupera solo la PRIMARY KEY , quindi lo riduce a 10, quindi recupera * solo 10 righe. Molto meno roba spalata in giro.

Riguardante COUNT su una tabella InnoDB:

  • INDEX(col) fa in modo che un indice la scansione funziona per SELECT COUNT(*) o SELECT COUNT(col) senza un WHERE .
  • Senza INDEX(col), SELECT COUNT(*)will use the "smallest" index; but SELECT COUNT(col)` avrà bisogno di una tabella scansiona.
  • Una scansione della tabella è solitamente più lento di una scansione dell'indice.
  • Attenzione ai tempi:è notevolmente influenzato dal fatto che l'indice e/o la tabella siano già memorizzati nella cache nella RAM.

Un'altra cosa su FULLTEXT è il + davanti alle parole -- per dire che ogni parola deve esistere, altrimenti non c'è corrispondenza. Ciò potrebbe ridurre i 30.000.

Il FULLTEXT index fornirà la date, id è un ordine casuale, non un ordine PK. Ad ogni modo, è 'sbagliato' assumere qualsiasi ordinamento, quindi è 'giusto' aggiungere ORDER BY , quindi lascia che l'ottimizzatore lo lanci se sa che è ridondante. E a volte l'Ottimizzatore può trarre vantaggio da ORDER BY (non nel tuo caso).

Rimuovendo solo il ORDER BY , in molti casi, rende una query molto più veloce. Questo perché evita di recuperare, ad esempio, 30.000 righe e di ordinarle. Invece fornisce semplicemente "qualsiasi" 10 righe.

(Non ho esperienza con Postgres, quindi non posso rispondere a questa domanda.)