Quali sono i vantaggi dell'utilizzo dei compilatori di query SQL?


17

Ci sono dei vantaggi nell'uso di un generatore di query, piuttosto che nell'utilizzo di SQL non elaborato?

Per esempio

$q->select('*')
  ->from('posts')
  ->innerJoin('terms', 'post_id')
  ->where(...)

vs:

SELECT * FROM posts WHERE ...

Vedo che molti framework utilizzano questo tipo di livelli di astrazione, ma non riesco a capire i vantaggi.


Penso che si dovrebbero scrivere query contro le viste e non contro le tabelle. Tendo a pensare che le persone che usano i compilatori di query tendano a non scrivere viste o chiedere ai DBA di crearle per loro. In tal modo non sfruttano tutta la potenza di RDBMS.
Tulains Córdova,

1
@ user61852: A parte forse un po 'di sicurezza e filtri gratuiti, cosa possono fornire query contro le viste che le query contro le tabelle non possono fornire?
Robert Harvey,

4
@RobertHarvey La stessa cosa che programmare con interfacce anziché con classi concrete. Disaccoppiamento e flessibilità. Il design delle tabelle sottostanti potrebbe essere casuale finché il "contratto", la vista, rimane "simulando" le stesse colonne di sempre.
Tulains Córdova,

@ user61852 Abbastanza giusto.
Robert Harvey,

@RobertHarvey L'ho trasformato in una risposta.
Tulains Córdova,

Risposte:


20

L'astrazione di scrivere l'SQL tramite un framework bene, gli abstract.

Scrivere SQL a mano non è poi così male da solo, ma inizi ad avere problemi con la fuga e la sanificazione e questo si trasforma in un disastro. Uno strato di astrazione può occuparsi di tutto ciò dietro le quinte, consentendo al codice di essere pulito e libero da molte mysql_real_escape_string()chiamate o simili.

Inoltre, ciò comporta la possibilità di contabilizzare diversi dialetti di SQL. Non tutti i database sono costruiti allo stesso modo e potrebbero esserci variazioni nelle parole chiave o nella sintassi di una determinata funzionalità. L'uso di un livello di astrazione consente di generare dinamicamente la sintassi corretta per la variante.

Mentre uno strato di astrazione può introdurre un impatto sulle prestazioni, è generalmente trascurabile rispetto alla pulizia e alla robustezza del codice che ricevi in ​​cambio.


1
Non penso che i dialetti SQL differiscano tra RDBMS. E in PHP c'è DOP che fa la sanificazione per te
Anna K.

12
I dialetti SQL differiscono, per questo vengono chiamati dialetti. Per quanto riguarda il DOP, lo strato di astrazione ci nasconde semplicemente questo casino.

@GlennNelson Anna significava qualsiasi dialetto, usando backend diversi (PSQL / MySQL / SQLite ...)
Izkata

2
@AnnaK. Il dialetto potrebbe non cambiare, ma a volte le caratteristiche sono diverse. Ad esempio, MySQL (con il motore MyISAM) non supporta le restrizioni di chiave esterna, mentre PostGres lo fa. O il dialetto dovrà gestire una cosa del genere (che richiede la piena conoscenza della struttura dei dati, come fa il Django ORM), o, più probabilmente: l'utente deve essere intelligente su come lo usa, che potrebbe farlo sembrare come il dialetto cambia, a seconda delle circostanze.
Izkata

1
+1 per lasciare che uno strumento ben costruito esegua la fuga e la sanificazione per te. Se riesce anche a convalidare, allora anche meglio.
Dan Ray,

11

I costruttori di query sono un mio odio per animali domestici, tanto che ho scritto il mio Framework (Apeel) per evitare di usarli!

Se usi la DOP (cosa che ti consiglio vivamente di fare), la santizzazione dell'input viene gestita per te.

Come ha detto qualcun altro, anche se facilitano il passaggio da un database all'altro, tendono a supportare la funzionalità del "minimo comune denominatore" e non supporteranno o avranno prestazioni peggiori per funzionalità più avanzate.

Ho sviluppato sistemi con database da circa il 1986 e in tutto quel tempo ho incontrato raramente un'azienda che cambiava effettivamente il database che utilizzava diverso da quando avevano bisogno di prestazioni migliori. Se stai modificando i database per prestazioni migliori, ha molto più senso dedicare il tuo tempo all'ottimizzazione manuale delle tue query per ottenere il meglio dal nuovo database anziché prendere il colpo di un generatore di query per motivi di semplicità.

Il tempo speso a fare i conti con le qwirks di un generatore di query (quindi riapprendendo quando si passa a una migliore) sarebbe molto più produttivo per imparare a ottimizzare il proprio SQL.

Comunque, ecco perché NON usarne uno, alcune persone li adorano però.


4

Teoricamente? Sì. Glenn Nelson ha sottolineato come spesso ti aiuteranno. (Se è un buon generatore di query).

In pratica? Non sempre all'altezza della teoria e potrebbe effettivamente causare problemi. Supponiamo che tu stia utilizzando un generatore di query su alcuni DBMS popolari e che tutto sia perfetto. Quindi un cliente ti chiede di colpire il proprio DBMS che presenta alcune stranezze che il generatore di query scelto non è in grado di gestire. (Ho riscontrato questo problema quando ho dovuto lavorare con una versione precedente di Pervasive.)

MA! Quello che dovresti assolutamente fare è separare il livello di accesso ai dati e assicurarti di poterlo sostituire con uno nuovo, se necessario. In questo modo puoi ottenere quel fantastico generatore di query con tutte le funzionalità ma se devi collegarne uno nuovo che utilizza quello strano pseudo-sql per il DB in questione.


2
Qualcosa come la stranezza del DB non dovrebbe essere risolto in anticipo? Voglio dire scoprire quale DB sta usando il tuo client e scegliere i framework / librerie adeguati di conseguenza è qualcosa che dovrebbe essere gestito prima di scrivere una singola riga di codice.

3

Penso che il vantaggio pratico e quotidiano del generatore di query - sia il riutilizzo del codice e la capacità di seguire il principio DRY.

Con il generatore di query è possibile inserire parti ripetute di SQL nei metodi. E quindi utilizzare questi metodi per comporre SQL complessi. Un esempio potrebbe essere ad esempio la clausola JOIN riutilizzabile:

function joinTaskWithClient($queryBuilder) {
    $queryBuilder->join('task', 'contract', 'task.contract_id = contract.id')
                 ->join('contract', 'client', 'contract.client_id = client.id');
}

Quindi l'utilizzo sarebbe:

$queryBuilder->select('client.name')
             ->from('client')
             ->where('task.id=:task')->setParameter('task', 42);
joinTaskWithClient($queryBuilder);

Come puoi notare, con il generatore di query puoi aggiungere parti di SQL in qualsiasi ordine (ad es. Parte JOIN dopo WHERE one) in contrasto con il caso quando raccogli manualmente la stringa SQL. Inoltre, puoi leggere il modello del costruttore per vederne le intenzioni e i vantaggi.

Concordo in merito alla fuga e alla sanificazione, ma ciò potrebbe essere ottenuto anche senza il generatore di query. Per quanto riguarda l'astrazione del tipo / dialetto del DB - questo è un vantaggio abbastanza teorico e discutibile, quasi mai usato nella pratica.


Per me, questo è anche un vantaggio principale. Un altro è che con l'astrazione in metodi puoi dare ai metodi nomi più significativi e persino creare un linguaggio specifico di dominio da questo, rendendo l'intento molto più chiaro. È anche possibile passare il generatore di query in giro e consentire a diversi componenti di aggiungervi i bit specifici. Ultimo ma non meno importante, ho scoperto che mi permetteva di incapsulare schemi dietro metodi con nomi significativi .... Ho trovato alcuni compilatori di query in cui l'aggiunta di colonne ha sovrascritto stupidamente quelle precedenti, il che rende un po 'inutile di quanto sopra ...
malte

2

fornirò una risposta basata sul file readme di un mio builder SQL personalizzato ( dialetto )

(segue il testo normale, rimossi i riferimenti specifici della libreria)

Requisiti

  1. Supporta più fornitori di DB (ad es. MySQL, PostgreSQL, SQLite, MS SQL / SQL Server, Oracle, DB2, ..)
  2. Esteso facilmente ai nuovi DB (preferibilmente attraverso un'impostazione di configurazione indipendente dall'implementazione)
  3. Modularità e trasferibilità indipendente dall'implementazione
  4. API flessibile e intuitiva

Caratteristiche

  1. modelli basati sulla grammatica
  2. supporto per visualizzazioni soft personalizzate
  3. db astrazione, modularità e trasferibilità
  4. modelli preparati
  5. fuga di dati

penso che le caratteristiche e i requisiti di cui sopra illustrino i motivi per cui si vorrebbe usare un generatore di astrazioni SQL

La maggior parte delle funzionalità di cui sopra sono supportate dalla maggior parte dei builder SQL (anche se non credo che tutti gli elenchi siano supportati, per quanto ne sappia)

Esempi di casi d'uso:

  1. Piattaforma CMS in grado di funzionare (senza alcuna modifica del codice sottostante) con più fornitori di DB
  2. Codice dell'applicazione personalizzato in cui il fornitore di database è suscettibile di modifiche e / o gli schemi dB sono dinamici (ciò significa che molte query non possono essere codificate ma devono essere astratte in modo da rendere il codice robusto per le modifiche)
  3. Prototipazione con un altro DB rispetto a quello utilizzato in produzione (richiederebbe una base di codice duplicata almeno per parte del codice)
  4. Il codice dell'applicazione non è strettamente associato al provider DB specifico e / o all'implementazione (anche all'interno dello stesso fornitore DB, ad esempio versioni diverse del fornitore DB), quindi è più robusto, flessibile e modulare
  5. Molti soliti casi di query e escape dei dati sono gestiti dal framework stesso e di solito questo è sia ottimale che più veloce

Infine, un esempio di un caso d'uso che ho avuto. stavo costruendo un'applicazione in cui lo schema di database sottostante (wordpress) non era adatto al tipo di query di dati che dovevano essere fatte, inoltre dovevano essere usate alcune delle tabelle WP (es. post) (quindi con tabelle completamente nuove per tutti i dati dell'applicazione non era un'opzione).

In quel caso, essere in grado di creare un'applicazione simile a MVC in cui il modello potrebbe essere interrogato da condizioni personalizzate / dinamiche ha reso la query hard-coding quasi un incubo. Immagina di dover supportare l'interrogazione di un massimo di 2-3 tabelle con join e di filtrare le condizioni per vedere a quale tabella unirti e cosa occuparti anche degli alias richiesti e così via.

Chiaramente si trattava di un caso d'uso di astrazione di query e, ancor di più, doveva (o almeno trarne un grande vantaggio) avere la capacità di definire viste soft personalizzate (un conglomerato di tabelle unite come se fossero una tabella personalizzata adatta al modello) . Quindi è stato molto più semplice, pulito, modulare e flessibile. In un altro aspetto, l'applicazione (codice) utilizzava anche il livello di astrazione della query come strumento di normalizzazione (schema db) . Come alcuni dicono, era a prova di futuro .

Se, domani, le persone decidono di aver bisogno di alcune opzioni o dati extra, è molto facile aggiungerlo al modello in un paio di righe e lavorare bene. Inoltre, se domani le persone decidono di non voler più usare wordpress (poiché l'applicazione è liberamente accoppiata a wordpress come plug-in), è anche relativamente facile cambiare ( solo la definizione di) i modelli in un paio di righe di codice per adattarsi al nuovo schema.

Capito quello che intendo?


1

Molto spesso, alcuni degli argomenti di queste query sono in effetti alcuni valori piuttosto che costanti. Ora, molti di questi sono essenzialmente derivati ​​dai post dei moduli utente. E quindi ci sono molte possibilità per attacchi di iniezione SQL. Quindi intrinsecamente la formazione delle query richiede una validazione completa.

Ora, questo non vuol dire che non ci fidiamo dello sviluppatore, ma la formazione della query potrebbe essere facile, ma ripetere tutti i possibili controlli di convalida ovunque potrebbe implicare che potresti perdere occasionalmente o modificare la query ma non modificare la query ma don aggiornare il controllo di convalida. Alcuni principianti potrebbero anche conoscere tutti i pericoli di perdere questo. Quindi l'astrazione del generatore di query è abbastanza essenziale.


0

Pensavo che i compilatori di query fossero app GUI che ti consentivano di selezionare tabelle e creare graficamente i join durante la generazione di SQL sotto il cofano, ma ora capisco che chiami anche i compilatori di query le API che forniscono un modo per non dover creare query SQL pure , astrattandoti così delle potenziali differenze nei gusti SQL.

L'uso di tali compilatori di query è buono , ma tendo a pensare che le persone che fanno molto affidamento su di loro tendono a non chiedere ai DBA: "ehi, questa è una query che uso molto, creane una visione".

Non fraintendetemi.

Penso che dovresti scrivere query su viste e non su tabelle. Non per sicurezza o filtro, che sono buoni motivi, ma per lo stesso motivo dovresti codificare contro interfacce e non contro classi concrete: il disaccoppiamento. Le viste sono come "contratti", allo stesso modo in cui le interfacce sono "contratti" in OOP. È possibile modificare le tabelle sottostanti, ma fintanto che si forza le viste a mostrare lo stesso "contratto" ai programmatori, il codice non deve interrompersi.

Ancora una volta, non fraintendetemi, è possibile utilizzare query builder per eseguire query sulle visualizzazioni, ma molte visualizzazioni nascono come un processo di maduration che è il prodotto di dover scrivere query e chiedere al DBA: "amico, crea questo, per favore" .

Sbaglio nel pensare che non scrivendo query non riesci a rilevare la necessità di creare determinate viste?

Un'altra cosa che mi preoccupa è che i programmatori principianti non padroneggiano SQL, uno dei più bei pezzi di tecnologia creati dall'uomo, non dovendo farlo.


Che ne dici di un DBA che dice "Questa query funziona male, lavoriamo insieme e miglioriamola". All'inizio potrebbe aver funzionato bene, ma ora si verificano problemi. Se tutto ciò che serve è un indice, perché disturbare lo sviluppatore con quello?
JeffO,

Questa è una situazione completamente diversa, ed è perfettamente OK.
Tulains Córdova,

Ho solo voglia di coinvolgere il DBA ogni volta che una query estrae un singolo record da una tabella o una vista crea un collo di bottiglia nel processo di sviluppo.
JeffO,
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.