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

Come accelerare il conteggio delle selezioni (*) con il gruppo per e dove?

Ecco alcune cose che proverei, in ordine di difficoltà crescente:

(più facile) - Assicurati di avere il giusto indice di copertura

CREATE INDEX ix_temp ON relations (relation_title, object_title);

Questo dovrebbe massimizzare le prestazioni dato il tuo schema esistente, poiché (a meno che la tua versione dell'ottimizzatore di MySQL non sia davvero stupida!) ridurrà al minimo la quantità di I/O necessari per soddisfare la tua query (a differenza se l'indice è nell'ordine inverso in cui l'intero indice deve essere scansionato) e coprirà la query in modo da non dover toccare l'indice cluster.

(un po' più difficile) - assicurati che i tuoi campi varchar siano il più piccoli possibile

Una delle sfide perf con gli indici varchar su MySQL è che, durante l'elaborazione di una query, l'intera dimensione dichiarata del campo verrà inserita nella RAM. Quindi, se hai un varchar(256) ma stai usando solo 4 caratteri, stai ancora pagando l'utilizzo di 256 byte di RAM mentre la query viene elaborata. Ahia! Quindi, se riesci a ridurre facilmente i tuoi limiti varchar, questo dovrebbe velocizzare le tue query.

(più difficile) - Normalizza

Il 30% delle tue righe con un valore di stringa singolo è un chiaro grido per la normalizzazione in un'altra tabella in modo da non duplicare le stringhe milioni di volte. Prendi in considerazione la normalizzazione in tre tabelle e l'utilizzo di ID interi per unirle.

In alcuni casi, puoi normalizzare sotto le coperte e nascondere la normalizzazione con viste che corrispondono al nome della tabella corrente... quindi devi solo rendere le tue query INSERT/UPDATE/DELETE consapevoli della normalizzazione ma puoi lasciare le tue SELECT da sole .

(più difficile) - Esegui l'hashing delle colonne di stringhe e indicizza gli hash

Se normalizzare significa modificare troppo codice, ma puoi modificare un po' il tuo schema, potresti prendere in considerazione la creazione di hash a 128 bit per le colonne delle stringhe (usando Funzione MD5 ). 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 eseguire l'hashing dei tuoi campi di stringa e quindi creare un indice sugli hash, ad es.

CREATE INDEX ix_temp ON relations (relation_title_hash, object_title_hash);

Nota che dovrai giocare con SELECT per assicurarti di eseguire il calcolo tramite l'indice hash e di non estrarre l'indice cluster (necessario per risolvere il valore di testo effettivo di object_title per soddisfare la query).

Inoltre, se relazione_titolo ha una piccola dimensione varchar ma il titolo dell'oggetto ha una dimensione lunga, allora puoi potenzialmente eseguire l'hashing solo di object_title e creare l'indice su (relation_title, object_title_hash) .

Nota che questa soluzione aiuta solo se uno o entrambi questi campi sono molto lunghi rispetto alla dimensione degli hash.

Si noti inoltre che ci sono interessanti impatti sulla distinzione tra maiuscole e minuscole dall'hashing, poiché l'hash di una stringa minuscola non è lo stesso di un hash di una maiuscola. Quindi dovrai assicurarti di applicare la canonicalizzazione alle stringhe prima di eseguirne l'hashing, in altre parole, eseguire l'hash solo in minuscolo se ti trovi 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.