Domanda

Supponiamo che una tabella denominata "log" contenga record enormi.

L'applicazione solitamente recupera i dati tramite un semplice SQL:

SELECT * 
FROM log 
WHERE logLevel=2 AND (creationData BETWEEN ? AND ?)

logLevel E creationData hanno indici, ma il numero di record richiede più tempo per recuperare i dati.

come lo aggiustiamo?

È stato utile?

Soluzione

Guardate il vostro piano di esecuzione / "SPIEGARE PIANO" risultato - se si recuperano grandi quantità di dati, allora c'è ben poco che si può fare per migliorare le prestazioni - si potrebbe provare a cambiare la sua dichiarazione SELECT di includere solo le colonne che ti interessa in, ma non cambierà il numero di letture logiche che si sta facendo e così ho il sospetto che avrà solo un effetto trascurabile sulle prestazioni.

Se sei solo recuperando un piccolo numero di record quindi un indice di LogLevel e un indice su CreationDate dovrebbe fare il trucco.

UPDATE: di SQL Server è in gran parte orientata intorno interrogazione piccoli sottoinsiemi di enormi database (ad esempio restituire un singolo record di un cliente da un database di milioni). La sua non è davvero rivolto per tornare davvero grandi insiemi di dati. Se la quantità di dati che si sta rinvio è davvero di grandi dimensioni, allora c'è solo una certa quantità che si sarà in grado di fare e quindi avrei dovuto chiedere:

Che cosa è che in realtà si sta tentando di raggiungere

  • Se si visualizzano i messaggi di log a un utente, poi si sono solo andando a essere interessati in un piccolo sottogruppo alla volta, e così si potrebbe anche voler esaminare metodi efficaci di dati SQL paging - se si sono solo tornando anche dire 500 o giù di lì record in un momento che dovrebbe essere ancora molto veloce.

  • Se si sta cercando di fare una sorta di analisi statistiche allora si potrebbe desiderare di replicare i dati in un archivio di dati più adatto ad analisi statistica. (Non so cosa però che non è la mia area di competenza)

Altri suggerimenti

1: non utilizzare mai Select *
2: assicurarsi che gli indici siano corrette, e le statistiche sono up-to-date
3: (facoltativo) Se trovate che non stai guardando i dati di log oltre un certo tempo (nella mia esperienza, se è successo più di una settimana fa, sono probabilmente non avrà bisogno di log per esso) ha istituito un lavoro da archivio che ad alcuni di back-up, e poi rimuovere i record non utilizzati. Che manterrà la dimensione della tabella verso il basso riducendo la quantità di tempo necessario cercare la tabella.

A seconda di quale genere di di database SQL che si sta utilizzando, si potrebbe guardare in Horizaontal partizionamento . Spesso, questo può essere fatto interamente sul lato del database delle cose in modo che non sarà necessario modificare il codice.

Avete bisogno di tutte le colonne? Il primo passo dovrebbe essere quello di selezionare solo quelli che effettivamente bisogno di recuperare.

Un altro aspetto è quello che si fa con i dati dopo che arriva alla vostra applicazione (compilare un insieme di dati / letto sequenzialmente /?).

Non ci può essere qualche potenziale di miglioramento sul lato della domanda di trasformazione.

Si dovrebbe rispondere da soli a queste domande:

Avete bisogno di contenere tutti i dati restituiti in memoria in una sola volta? Quanta memoria si alloca per riga sul lato recupero? Quanta memoria avete bisogno in una sola volta? Si può riutilizzare qualche ricordo?

Un paio di cose

Non è necessario tutte le colonne, la gente di solito fanno SELECT * perché sono troppo pigro per lista 5 colonne del 15 che la tabella ha.

acquistare più RAM, themore RAM si hanno le più dati possono vivere nella cache che è 1000 volte più veloce della lettura dal disco

Per me ci sono due cose che puoi fare,

  1. Partiziona la tabella orizzontalmente in base alla colonna della data

  2. Utilizzare il concetto di preaggregazione.

Preaggregazione:In preagg avresti una tabella "logs", una tabella "logs_temp", una tabella "logs_summary" e una tabella "logs_archive".La struttura della tabella logs e logs_temp è identica.Il flusso dell'applicazione sarebbe in questo modo, tutti i log vengono registrati nella tabella dei log, quindi ogni ora viene eseguito un processo cron che esegue le seguenti operazioni:

UN.Copia i dati dalla tabella dei log alla tabella "logs_temp" e svuota la tabella dei log.Questo può essere fatto usando il trucco della Tabella delle Ombre.

B.Aggrega i log per quella particolare ora dalla tabella logs_temp

C.Salva i risultati aggregati nella tabella di riepilogo

D.Copia i record dalla tabella logs_temp alla tabella logs_archive e quindi svuota la tabella logs_temp.

In questo modo i risultati vengono preaggregati nella tabella riepilogativa.

Ogni volta che desideri selezionare il risultato, lo selezionerai dalla tabella di riepilogo.

In questo modo le selezioni sono molto veloci, perché il numero di record è molto inferiore in quanto i dati sono stati preaggregati ogni ora.Potresti anche aumentare la soglia da un'ora a un giorno.Dipende dai tuoi bisogni.

Ora anche gli inserimenti sarebbero veloci, perché la quantità di dati non è molta nella tabella dei registri poiché contiene i dati solo per l'ultima ora, quindi la rigenerazione dell'indice sugli inserti richiederebbe molto meno tempo rispetto a set di dati molto grandi, quindi rendendo veloci gli inserti.

Puoi leggere di più sul trucco della Tabella delle Ombre Qui

Ho utilizzato il metodo di preaggregazione in un sito di notizie basato su WordPress.Ho dovuto sviluppare un plugin per il sito web di notizie che mostrasse notizie recentemente popolari (popolari negli ultimi 3 giorni), e ci sono circa 100.000 contatti al giorno, e questa cosa della pre-aggregazione ci ha davvero aiutato molto.Il tempo di interrogazione è sceso da più di 2 secondi a meno di un secondo.Ho intenzione di rendere presto disponibile pubblicamente il plugin.

Come per altre risposte, non utilizzare 'select *' a meno che non si ha realmente bisogno di tutti i campi.

  

logLevel e creationData hanno indici

È necessario un unico indice con entrambi i valori, che ordine li metti in influisce sulle prestazioni, ma a patto di avere un piccolo numero di possibili valori del livello di log (e il dato non sia inclinato) si otterrà una migliore performance mettendo prima creationData .

Si noti che in modo ottimale un indice ridurrà il costo di una query per accedere (N) vale a dire che sarà ancora ottenere più lento come il numero di aumenti record.

C.

Spero davvero che si creationData creationDate media.

Prima di tutto, non è sufficiente avere indici su logLevel e creationData. Se si dispone di 2 indici separati, Oracle sarà in grado di utilizzare 1. Quello che vi serve è un singola indice su entrambi i campi:

CREATE INDEX i_log_1 ON log (creationData, logLevel);

Si noti che ho messo prima creationData. In questo modo, se si mette solo quel campo nella clausola WHERE, sarà ancora in grado di utilizzare l'indice. (Filtraggio su un solo data sembra più probabile scenario che sul fare il login livello).

Quindi, assicurarsi che la tabella è popolata con i dati (come dati tanto quanto si intende utilizzare in produzione) e aggiornare le statistiche sul tavolo.

Se la tabella è di grandi dimensioni (almeno alcune centinaia di migliaia di righe), utilizzare il seguente codice per aggiornare le statistiche:

DECLARE
  l_ownname          VARCHAR2(255) := 'owner'; -- Owner (schema) of table to analyze
  l_tabname          VARCHAR2(255) := 'log'; -- Table to analyze
  l_estimate_percent NUMBER(3) := 5;  -- Percentage of rows to estimate (NULL means compute)
BEGIN
  dbms_stats.gather_table_stats (
     ownname => l_ownname ,
      tabname => l_tabname,
      estimate_percent => l_estimate_percent,
      method_opt => 'FOR ALL INDEXED COLUMNS',
      cascade => TRUE
  );
END;

In caso contrario, se la tabella è di piccole dimensioni, l'uso

ANALYZE TABLE log COMPUTE STATISTICS FOR ALL INDEXED COLUMNS;

Inoltre, se la tabella cresce di grandi dimensioni, si shoud considerare partizionarlo per fascia sulla colonna di creationDate. Vedere questi collegamenti per i dettagli:

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top