Come creare rapporti per una webapp di e-commerce senza rallentarlo

0

Abbiamo un sito di e-commerce di medie dimensioni interamente costruito su misura utilizzando database Java e MySQL sull'infrastruttura AWS. In un periodo di diversi anni, il volume degli ordini è cresciuto notevolmente e quindi la dimensione del nostro database.

Negli ultimi due mesi ci troviamo di fronte a un problema di CRM lento (applicazione di amministrazione), in particolare di segnalazione. Questi rapporti sono costruiti principalmente attorno ai clienti e ai dati degli ordini. Pochi punti da notare sul nostro sistema

  • Abbiamo due app Web: storefront & applicazione CRM back-end
  • Storefront è in gran parte memorizzato nella cache, quindi l'impatto non è molto visibile lì
  • CRM e storefront sono connessi a un singolo server di database con un singolo schema
  • Abbiamo aggiunto diversi indici nelle nostre tabelle clienti, ordine e ordine_item per aumentare la velocità delle query utilizzate nei rapporti.
  • Queste tre tabelle sono utilizzate principalmente per scopi di reporting. Anche il sito Web continua ad aggiungere nuovi record in queste tabelle quando un nuovo utente registra o posiziona l'ordine.
  • AWS RDS utilizzato come server database eseguito in media al 35% della CPU
  • Se eseguo queste query direttamente su RDS usando MySql workbench, allora è anche lento.

Voglio capire, come potrei migliorare le prestazioni della nostra applicazione CRM. Qual è l'area chiave in cui devo lavorare su cui avrà un impatto sostanziale.

  • È un'infrastruttura? Server database migliore?
  • È necessaria l'ottimizzazione delle query?
  • È necessaria una migliore indicizzazione nei tavoli?

Modifica - Aggiunta query di esempio

Ad esempio, eseguo la query seguente sulla tabella ordini per recuperare il conteggio degli ordini per una data specifica. Ci vogliono circa 3 secondi in media per restituire i dati. Prevedo che query come questa non dovrebbero richiedere più di un secondo di tempo.

SELECT count(*) as Count FROM orders WHERE date(CONVERT_TZ(CreatedDate,'+00:00','+05:30')) = '2018-07-30' 
AND OrderStatusId IN (5,10,15) AND Deleted = 0

Esistono diverse query di questo tipo, che vengono attivate per creare un report. Che alla fine presenta un rapporto all'utente non inferiore a 10-20 secondi

Modifica : ha aggiunto query modificate e il loro tempo di risposta

Come per le risposte, ho testato questa query senza la funzione convert_tz e una senza convert_tz e date . Ma i risultati non sono abbastanza buoni. C'è un guadagno di appena 300 ms se rimuovo entrambe le funzioni convert_tz e date . L'ho testato più volte, e ogni volta questa è la differenza tra queste query.

  1. Query 1 - tempo impiegato = 4,91 secondi

SELECT count(*) as Count FROM orders WHERE date(CreatedDate) = '2018-07-30' AND OrderStatusId IN (5,10,15) AND Deleted = 0;

  1. Query 2 - tempo impiegato = 1,72 secondi

SELECT count(*) as Count FROM orders WHERE CreatedDate >= '2018-07-30 00:00:00' AND CreatedDate <= '2018-07-30 23:59:59' AND OrderStatusId IN (5,10,15) AND Deleted = 0;

  1. Query 3 - tempo impiegato = 2.02 sec

SELECT count(*) as Count FROM orders WHERE date(CONVERT_TZ(CreatedDate,'+00:00','+05:30')) = '2018-07-30' AND OrderStatusId IN (5,10,15) AND Deleted = 0;

    
posta Abhishek Sharma 30.07.2018 - 14:07
fonte

2 risposte

2

Dato che hai notato che le tue query sono lente quando usi MySql Workbench, questo è il primo punto di partenza.

In Sql Server, è possibile visualizzare il piano di query per una query e vedere esattamente come lo elaborerà il database. Inoltre, puoi controllare per vedere quale indice (se esiste) è usato.

Nel caso della tua query di esempio, la tua clausola WHERE contiene un calcolo CONVERT_TZ(CreatedDate...) . Sql Server vedrebbe questo e ricorrere a una scansione della tabella: leggerà ogni record nella tabella, eseguirà questa conversione e quindi filtrerà di conseguenza. È incredibilmente lento se hai molti record.

Se possibile, aggiungi un nuovo campo a tale tabella CreatedDateUTC ed esegui il calcolo una volta. In seguito potrai creare un indice su quel campo.

In altre parole, inizia con i tuoi ultimi due proiettili

Optimization in queries needed?
Better indexing in tables needed?

    
risposta data 30.07.2018 - 16:15
fonte
1

La risposta standard al problema dei report, che per loro natura sono lenti da calcolare, è eseguirli contro un server di data warehouse piuttosto che sul database transazionale.

Ciò richiede l'esportazione dei dati dal DB transazionale. Normalmente questo può essere fatto come un processo continuo.

Un database del data warehouse è strutturato in modo diverso per consentire query veloci in stile report e, poiché si tratta di un server diverso, le query non influiscono sulle prestazioni dell'applicazione.

Tuttavia! il tuo esempio SQL sembra piuttosto semplice. È probabilmente lento a causa della conversione di ogni data di righe in un determinato fuso orario. Questo è facilmente risolvibile con la pratica standard di memorizzare le date come UTC.

Potrebbe essere che una semplice ottimizzazione delle query ti consenta di eseguire i tuoi rapporti sul DB transazionale o una semplice replica del tuo database su un server di failover / reporting

    
risposta data 30.07.2018 - 17:59
fonte

Leggi altre domande sui tag