Qui ci sono diverse cose che mi piacerebbe provare, in ordine di difficoltà crescente:
(più facile) - Assicurati di avere il diritto di copertura dell'indice
CREATE INDEX ix_temp ON relations (relation_title, object_title);
Questo dovrebbe massimizzare il rendimento dato lo schema esistente, poiché (a meno che la tua versione dell'ottimizzatore di MySQL sia davvero stupido!) Ridurrà al minimo la quantità di I/O necessaria per soddisfare la tua query (diversamente dall'indice nell'ordine inverso dove tutto indice deve essere scansionato) e coprirà la query in modo da non dover toccare l'indice cluster.
(un po 'più difficile) - assicurarsi che il proprio campi varchar sono il più piccolo possibile
Una delle sfide Potenza con gli indici varchar su MySQL è che, durante l'elaborazione di una query, il full size dichiarato della il campo verrà inserito nella RAM. Quindi se hai un varchar (256) ma stai usando solo 4 caratteri, stai ancora pagando l'utilizzo della RAM a 256 byte mentre la query viene elaborata. Ahia! Quindi, se puoi ridurre facilmente i tuoi limiti varchar, questo dovrebbe velocizzare le tue domande.
(più difficile) - Normalizzare
il 30% dei tuoi file con un singolo valore stringa è un grido chiaro per la normalizzazione in un'altra tabella in modo che non stai duplicando stringhe milioni di volte. Considera la normalizzazione in tre tabelle e l'utilizzo di ID interi per unirle.
In alcuni casi, è possibile normalizzare sotto le copertine e nascondere la normalizzazione con viste che corrispondono al nome della tabella corrente ... quindi è necessario rendere le query INSERT/UPDATE/DELETE consapevoli della normalizzazione, ma è possibile lascia i tuoi SELECT da solo.
(più difficile) - Hash le colonne di stringa e l'indice gli hash
Se normalizzare mezzi che cambiano troppo codice, ma è possibile modificare lo schema un po ', si può prendere in considerazione la creazione di hash a 128 bit per le colonne delle stringhe (utilizzando MD5 function). In questo caso (a differenza della normalizzazione) non è necessario modificare tutte le query, solo gli INSERT e alcuni SELECT. Ad ogni modo, ti consigliamo di hash i tuoi campi di stringa e quindi di creare un indice sugli hash, ad es.
CREATE INDEX ix_temp ON relations (relation_title_hash, object_title_hash);
Si noti che avrete bisogno di giocare con il SELECT per assicurarsi che si sta facendo il calcolo tramite l'indice hash e non tirando in indice cluster (necessario per risolvere il valore di testo effettivo della object_title al fine per soddisfare la richiesta).
Inoltre, se relation_title ha una piccola dimensione varchar ma il titolo dell'oggetto ha una dimensione lunga, è possibile potenzialmente eseguire l'hash solo object_title e creare l'indice su (relation_title, object_title_hash)
.
Si noti che questa soluzione è utile solo se uno o entrambi questi campi sono molto lunghi rispetto alla dimensione degli hash.
Si noti inoltre che vi sono interessanti impatti sulla distinzione tra maiuscole e minuscole e casi di collazione, poiché l'hash di una stringa minuscola non è uguale a un hash di uno maiuscolo. Quindi dovrai assicurarti di applicare la canonicalizzazione alle stringhe prima di eseguirne l'hashing - in altre parole, solo hash in minuscolo se sei in un DB senza distinzione tra maiuscole e minuscole. Potresti anche voler tagliare gli spazi dall'inizio o dalla fine, a seconda di come il tuo DB gestisce gli spazi iniziali/finali.
Potresti fornire ulteriori dettagli, ad es. l'intera selezione e la struttura della tabella? Un altro primo colpo: stai usando gli indici? – Kosi2801
Di seguito ho aggiunto alcune soluzioni potenziali, ma concordo con Kosi sul fatto che vedere la definizione della tabella (in particolare la lunghezza delle colonne varchar!) E le definizioni dell'indice sarebbero molto utili per diagnosticare ciò. –
Le relazioni sono una tabella Innodb o MyISAM? –