Algoritmo adatto per l'unione di record da più database

4

Sono in procinto di scrivere una libreria che è utilizzata per poter accedere ai dati da un database. La libreria richiede la definizione iniziale di tutte le tabelle che l'applicazione utilizzerà sotto forma di classi che estendono una classe astratta all'interno della libreria.

Queste classi contengono la connessione al database in cui è memorizzata la tabella, il nome della tabella, le colonne, gli indici e le relazioni tra le tabelle. La classe astratta contiene funzioni statiche che consentono a un utente di select o insert righe in quel particolare database.

La funzione select restituisce un oggetto che consente di assemblare una query, che fornisce opzioni per fields , joins , where , group , having , order e limit , che culmina in una funzione fetch che restituisce un oggetto che contiene i record risultanti insieme alle funzioni save e delete .

Ora funziona bene quando funziona tra le tabelle all'interno dello stesso database, quando viene combinato con tabelle in altri database, ma sto cercando di ottenerlo in modo che possa fare qualcosa del genere:

class tabA extends tableBase {
    public static $database  = 'mySqlDB';
    public static $tablename = 'tableA';
    public static $columns   = array(
        'tableAID'       => 'int(11)',
        'tableAKey'      => 'varchar(128)',
        'tableBRefID'    => 'int(11)',
    );
}

class tabB extends tableBase {
    public static $database  = 'oracleDB';
    public static $tablename = 'tableB';
    public static $columns   = array(
        'tableBID'       => 'int(11)',
        'tableBSpecial'  => 'boolean',
        'tableBValue'    => 'text',
    );
}

tabA::select()->join('tabB', 'LEFT')->where(andCondition(eqCondition(tabA::tableAKey, 'foo'), eqCondition(tabB::tableBSpecial, true)))->fetch()

Dove il ritorno di fetch comprenderà le righe contenenti le colonne trovate dai due database.

I driver per i database utilizzano un'interfaccia comune, di cui la funzione di selezione ha il seguente aspetto:

function select ($columns, $from, $joins, $where, $group, $having, $order, $limit, $offset)

Sono consapevole che la classe tableBase dovrà suddividere la query che verrà eseguita in due query separate, una per eseguire query da tabA e una da tabB, quindi unire i risultati nel tipo definito (in questo caso, SINISTRA join). Ma sto avendo problemi a trovare un algoritmo adatto per dividere la query in due blocchi di query separati, quindi come combinare i risultati (soddisfacendo la condizione where ) in un maniero efficiente.

I miei pensieri finora implicherebbero la rimozione delle colonne (esclusi i campi derivati dalle operazioni tra i dati sui due database) e le condizioni che sono rilevanti per ciascun database, utilizzando quelle ricerche su ciascun database, passando attraverso i risultati del risultati della tabella del database principale e dati di unione (scartando le righe che non corrispondono al join), (a questo punto, se ci sono campi derivati come indicato sopra, vengono calcolati), quindi infine passano attraverso tutte le righe risultanti per garantire che qualsiasi rimanente dove o si verificano le condizioni, e applicando eventuali ordini finali.

Ma a mio parere, questo non sembra il maniero più efficiente e crea problemi quando si usano i limiti, a meno che non recuperi tutte le righe, quindi applichi l'operazione limite sul risultato finale.

Quindi, ci sono risorse o informazioni su come una cosa del genere potrebbe essere realizzata in un modo migliore / più efficiente / più ordinato?

ULTERIORI

Sebbene si tratti di database SQL, un database NoSQL potrebbe funzionare a patto che il driver costruito funzioni entro i confini dell'interfaccia del driver del database. Al momento, esiste un solo driver che utilizza PDO, ma sto lavorando alla creazione di driver per datastore XML e MongoDB.

    
posta topherg 09.05.2013 - 18:07
fonte

1 risposta

1

Resta con me se questa è una risposta semplicistica, ma non credo di vedere nulla di specifico che vieta questo nella tua domanda.

Se hai aggiunto gli specificatori di database agli specificatori di tabella in SELECT , passerai il carico della gestione tra database ai server di database. Diversi RDBMS lo consentono.

es. invece di

USE a; SELECT x FROM test;     
USE b; SELECT x, y FROM test; 
(emulation of JOIN between the two cursors)

useresti

SELECT db2.test.y FROM db2.test JOIN db1.test ON db1.test.x = db2.test.x;

Ovviamente il tuo driver sarebbe quindi meno di "universale", e meno (o per nulla) parallelizzabile, e non saresti in grado di dividere le tabelle tra due server diversi o due RDBMS diversi (MySQL e Postgres), o anche due diversi livelli di accesso allo stesso server. Ma forse i vantaggi in termini di tempo di sviluppo e debug ottenuti in questo modo varrebbero la pena di questi limiti?

    
risposta data 25.05.2013 - 12:02
fonte

Leggi altre domande sui tag