La funzionalità nel DB è un blocco della scalabilità?


17

Potrei non essere in grado di dare il titolo giusto alla domanda. Ma eccolo qui,

Stiamo sviluppando un portale finanziario per la gestione patrimoniale. Ci aspettiamo che oltre 10000 clienti utilizzino l'applicazione. Il portale calcola varie analisi delle prestazioni basate sull'analisi tecnica del mercato azionario.

Abbiamo sviluppato molte funzionalità attraverso Stored procedure, funzioni definite dall'utente, trigger ecc. Tramite Database. Pensavamo di poter ottenere un enorme incremento delle prestazioni facendo cose direttamente nel database che attraverso il codice C #. E in realtà abbiamo avuto un enorme aumento delle prestazioni.

Quando ho cercato di vantarmi del raggiungimento del nostro CTO, ha messo in dubbio la mia decisione di implementare funzionalità nel database piuttosto che nel codice. Secondo lui tali applicazioni soffrono di problemi di scalabilità. Nelle sue parole "In questi giorni le cose sono conservate nella memoria / cache. I dati del cluster sono difficili da gestire nel tempo. Facebook, Google non ha nulla nel database. È l'era dei thin server e dei thin client. DB viene utilizzato solo per archiviare dati semplici e la funzionalità dovrebbe essere completamente disaccoppiata dal database. "

Ragazzi, per favore, potete darmi qualche suggerimento sul fatto che quello che dice sia giusto. Come fare per progettare un'applicazione del genere?


3
"e in realtà abbiamo avuto un enorme aumento delle prestazioni" rispetto a cosa? Quando non hai mai implementato la stessa funzionalità su un client, come fai a saperlo?
Doc Brown,

3
Penso che sarà il solito - dipende dal progetto, dall'implementazione dei dati e dall'abilità del team.
Daniel Iankov,

1
Dovresti chiedere al tuo CTO cosa gli fa pensare che i database non stiano usando le sue tecniche preferite e perché le procedure memorizzate non si qualificano come "codice".
Blrfl,

3
Facebook e Google hanno problemi su una scala completamente diversa rispetto alla maggior parte delle applicazioni: potrebbe esserci un problema con la quantità di dati che devi trattare in termini di dati dal mercato, ma i database SQL contemporanei sono costruiti per far fronte a quantità sorprendenti di dati.
Murph,

1
Probabilmente penserei allo stesso modo del tuo CTO a meno che tu non possa dimostrare che le prestazioni della sua soluzione erano insufficienti e non c'erano altri modi per gestirlo. Le procedure memorizzate, specialmente quando il loro numero aumenta, causano un'enorme barriera che si sposta su altri DB se necessario ... non è possibile prevedere il futuro.
Rig

Risposte:


23

In breve, sarei d'accordo con il tuo CTO. Probabilmente hai ottenuto alcune prestazioni a spese della scalabilità (se quei termini sono confusi, chiarirò di seguito). Le mie due maggiori preoccupazioni sarebbero la manutenibilità e la mancanza di opzioni per ridimensionare orizzontalmente (supponendo che ne avrete bisogno).

Vicinanza ai dati: facciamo un passo indietro. Ci sono alcuni buoni motivi per inserire il codice in un DB. Direi che il più grande sarebbe la vicinanza ai dati - ad esempio, se ti aspetti che un calcolo restituisca una manciata di valori, ma queste sono aggregazioni di milioni di record, che inviano i milioni di record (su richiesta) la rete da aggregare altrove è estremamente dispendiosa e potrebbe uccidere facilmente il tuo sistema. Detto questo, è possibile ottenere questa vicinanza di dati in altri modi, essenzialmente utilizzando cache o DB di analisi in cui parte dell'aggregazione viene eseguita in anticipo.

Esecuzione del codice nel DB:Gli effetti secondari sulle prestazioni, come la "memorizzazione nella cache dei piani di esecuzione", sono più difficili da discutere. A volte, i piani di esecuzione memorizzati nella cache possono essere una cosa molto negativa, se il piano di esecuzione errato è stato memorizzato nella cache. A seconda del tuo RDBMS, potresti ottenere il massimo da questi, ma nella maggior parte dei casi non otterrai molto rispetto all'SQL parametrizzato (anche quei piani vengono generalmente memorizzati nella cache). Direi anche che la maggior parte dei linguaggi compilati o JIT in genere funzionano meglio dei loro equivalenti SQL (come T-SQL o PL / SQL) per operazioni di base e programmazione non relazionale (manipolazione di stringhe, loop, ecc.), Quindi non perderai nulla lì, se hai usato qualcosa come Java o C # per fare il crunching dei numeri. Anche l'ottimizzazione a grana fine è piuttosto difficile: sul DB, spesso bloccato con un B-tree generico (indice) come unica struttura di dati. Ad essere onesti, un'analisi completa, tra cui cose come avere transazioni a più lungo termine, escalation dei blocchi, ecc., Potrebbe riempire i libri.

Manutenibilità: SQL è un linguaggio meraviglioso per ciò per cui è stato progettato. Non sono sicuro che si adatti perfettamente alla logica dell'applicazione. La maggior parte degli strumenti e delle pratiche che rendono sopportabili le nostre vite (TDD, refactoring, ecc.) Sono difficili da applicare alla programmazione di database.

Prestazioni contro scalabilità:Per chiarire questi termini, intendo questo: le prestazioni sono la velocità con cui ti aspetteresti che una singola richiesta passi attraverso il tuo sistema (e torni all'utente), per il momento assumendo un carico ridotto. Questo sarà spesso limitato da cose come il numero di livelli fisici che attraversa, quanto sono ottimizzati quei livelli, ecc. La scalabilità è come le prestazioni cambiano con l'aumentare del numero di utenti / carico. Potresti avere prestazioni medio / basse (diciamo, 5 secondi + per una richiesta), ma una scalabilità eccezionale (in grado di supportare milioni di utenti). Nel tuo caso, probabilmente sperimenterai buone prestazioni, ma la tua scalabilità sarà limitata da quanto è grande un server che puoi costruire fisicamente. Ad un certo punto, colpirai quel limite e sarai costretto a ricorrere a cose come lo sharding, che potrebbe non essere fattibile a seconda della natura dell'applicazione.

Ottimizzazione precoce: in definitiva, penso che tu abbia fatto l'errore di ottimizzare prematuramente. Come altri hanno sottolineato, in realtà non hai misurazioni che mostrano come funzionerebbero gli altri approcci. Bene, non possiamo sempre costruire prototipi su larga scala per dimostrare o confutare una teoria ... Ma in generale, sarei sempre restio a scegliere un approccio che scambia la manutenibilità (probabilmente la qualità più importante di un'applicazione) per le prestazioni .

EDIT: su una nota positiva, il ridimensionamento verticale può allungare abbastanza lontano in alcuni casi. Per quanto ne so, SO è stato eseguito su un singolo server per un bel po 'di tempo. Non sono sicuro di come corrisponda ai tuoi 10.000 utenti (immagino che dipenderebbe dalla natura di ciò che stanno facendo nel tuo sistema), ma ti dà un'idea di cosa si può fare (in realtà, ci sono esempi più impressionanti, questo sembra essere un popolare che la gente può facilmente capire).

EDIT 2: Per chiarire e commentare alcune cose sollevate altrove:

  • Ri: Consistenza atomica - La coerenza ACID potrebbe essere un requisito del sistema. Quanto sopra non discute davvero, e dovresti capire che la coerenza ACID non richiede di eseguire tutta la tua logica aziendale all'interno del DB. Spostando il codice che non ha bisogno di essere presente nel DB, lo si sta vincolando per essere eseguito nell'ambiente fisico del resto del DB - è in competizione per le stesse risorse hardware dell'effettiva porzione di gestione dei dati del proprio DB. Per quanto riguarda il ridimensionamento del codice solo su altri server DB (ma non sui dati effettivi), questo può essere possibile , ma cosa guadagni esattamente qui, a parte i costi di licenza aggiuntivi nella maggior parte dei casi? Tieni le cose che non hanno bisogno di essere sul DB, fuori dal DB.
  • Ri: prestazioni SQL / C # - poiché questo sembra essere un argomento di interesse, aggiungiamo un po 'alla discussione. Puoi certamente eseguire il codice nativo / Java / C # all'interno dei DB, ma, per quanto ne so, non è quello che è stato discusso qui - stiamo confrontando l'implementazione del codice tipico dell'applicazione in qualcosa come T-SQL rispetto a qualcosa come C #. Esistono numerosi problemi che in passato sono stati difficili da risolvere con il codice relazionale, ad esempio si consideri il problema "accessi concomitanti massimi", in cui sono presenti record che indicano un accesso o una disconnessione e l'ora e è necessario capire quali era il numero massimo di utenti che hanno effettuato l'accesso contemporaneamente. La soluzione più semplice possibile è quella di scorrere i record e continuare a incrementare / decrementare un contatore quando si verificano accessi / disconnessioni e tenere traccia del massimo di questo valore.Maggio, Non lo so), il meglio che puoi fare è un CURSORE (le soluzioni puramente relazionali sono tutte su diversi ordini di complessità e il tentativo di risolverlo usando un ciclo while si traduce in prestazioni peggiori). In questo caso, sì, la soluzione C # è in realtà più veloce di quella che puoi ottenere in T-SQL, punto. Ciò può sembrare inverosimile, ma questo problema può manifestarsi facilmente nei sistemi finanziari, se si lavora con righe che rappresentano modifiche relative e è necessario calcolare aggregazioni con finestre su quelle. Anche le invocazioni di proc memorizzate tendono ad essere più costose: invocare un SP banale un milione di volte e vedere come si confronta con la chiamata a una funzione C #. Ho accennato ad alcuni altri esempi sopra - non ho ancora incontrato nessuno implementare una tabella hash corretta in T-SQL (uno che in realtà offre alcuni vantaggi), mentre è abbastanza facile da fare in C #. Ancora una volta, ci sono cose in cui i DB sono fantastici e cose in cui non sono così fantastici. Proprio come non vorrei fare JOIN, SUM e GROUP BY in C #, non voglio scrivere nulla di particolarmente intenso sulla CPU in T-SQL.

Uno dei motivi per cui tendo a trasferire funzionalità al database è che è molto meno difettoso del codice a livello di applicazione. SQL è dichiarativo e non soffre di molti dei problemi delle lingue imperative.
wobbily_col,

Per quanto riguarda la manutenibilità, l'utilizzo della manutenibilità di SQL Server Data Tools è un gioco da ragazzi. In effetti per qualsiasi database non banale (uno con più di 5 tabelle) lo considererei un requisito.
Jon49,

4

La scalabilità non ha nulla a che fare con la posizione dei dati o con il modo in cui avviene il calcolo. La scalabilità riguarda tutto il modo in cui gestisci l'interdipendenza globale di dati e stato. Se la tua architettura è contorta con tutti i tipi di interdipendenze di dati, non importa dove metti il ​​codice per trasformare quei dati. Le interdipendenze stanno per forzare la tua mano e ridurre qualsiasi potenziale per ridimensionare le cose. Se, d'altra parte, i dati sono accoppiati in modo approssimativo e lo stato globale è molto piccolo o assente, allora di nuovo non importa dove avvenga il calcolo. Scalare le cose sarà molto più semplice.

Non sono sicuro di dove il tuo CTO stia ottenendo le sue informazioni sui problemi di scalabilità, ma da quello che hai detto non sembra che abbia dei veri motivi per mettere in discussione l'attuale decisione sull'architettura oltre alle tendenze della moda del software. Basare le decisioni architettoniche su tali tendenze è generalmente una cattiva idea.


1
+1 perScalability is all about how you manage global state and data inter-dependence.
Estefany Velez,

2

E in realtà abbiamo avuto un enorme aumento delle prestazioni.

Penso che devi stabilire un benchmark delle prestazioni e iniziare a costruire prima il tuo prototipo. Mantenere tutta la logica in DB è una vecchia scuola (imho, non ho nulla contro di essa) di gestire l'architettura client-server. Sebbene abbia i suoi vantaggi, ci sono molti inconvenienti che devono essere considerati.

L'approccio usuale per questo tipo di applicazioni vendibili viene fatto tramite SOA . Perché a lungo termine, questo è il modo più semplice per aggiungere nuove applicazioni client al progetto.

Hai anche menzionato i trigger. L'utilizzo del trigger potrebbe diventare un grosso problema più avanti nel ciclo di vita del supporto dell'applicazione, farei due volte attenzione con esso e proverei persino a saltare il suo utilizzo.


2

Il tuo CTO è sbagliato al 100%.

I tuoi numeri finanziari DEVONO sommarsi in ogni momento. Ciò significa che hai bisogno di ACID e DB relazionale sono il posto migliore per assicurarlo. I guadagni in termini di prestazioni di NoSql DB sono generalmente a carico di ACID e questo è OK per Google e Facebook, MA NON per un sistema contenente dati finanziari.

Dire che C # funziona meglio del codice SQL è anche idiozia ...


Dire che C # funziona meglio del codice SQL è anche idiozia ... - Ma non stai negando che il codice C # sia più scalabile, giusto?
Jim G.

No, non è più scalabile, poiché non è dove si trova il collo della bottiglia, posso ridimensionare il codice Sql (non i dati) in orizzontale con la stessa facilità con cui posso ridimensionare in orizzontale il codice C #.
Morons,

@JimG. Solo per chiarire, "Posso ridimensionare il codice Sql (non i dati) orizzontalmente con la stessa facilità con cui posso ridimensionare il codice C # in orizzontale" se è stato progettato per farlo ... Come C # deve essere progettato per ridimensionare. Non puoi semplicemente dire di ridimensionare C # meglio, si tratta di pianificare non la lingua.
Morons,

@JimG .: Il software che non si adatta può essere scritto in qualsiasi lingua, incluso C #. Qualsiasi database degno di nota può avere stored procedure scritte in lingue diverse dalla loro implementazione nativa di SQL-ish e le persone che vanno in profondità con NoSQL in situazioni che richiedono ACID di solito finiscono per reinventare la maggior parte delle ruote che sono state ben progettate implementato dal DBMS.
Blrfl,

@Morons: penso che siamo d'accordo. Io ero in effetti confondendo i dati con "SQL". È molto più costoso ridimensionare il database.
Jim G.

2

Ogni volta che qualcuno menziona la scalabilità e Google / Facebook / Twitter / ecc., È un'aringa rossa. A meno che non forniate essenzialmente lo stesso servizio, ciò che funziona per loro potrebbe non essere adatto a voi. In generale, se puoi scalare da una singola macchina a un cluster di otto macchine, probabilmente hai coperto tutte le tue basi. A meno che tu non abbia un duro requisito aziendale per offrire 20 milioni di visualizzazioni di pagina al giorno, non preoccuparti dell'hyper-ridimensionamento. Fai ciò che ha senso per i reali requisiti della tua applicazione e preoccupati di ridimensionare quando diventa ovvio che devi farlo. E non dimenticare che anche la maggior parte dei server di database può essere raggruppata, quindi solo perché è tutto in un database non significa che sia su un server.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.