Visualizzazione post con etichetta database. Mostra tutti i post
Visualizzazione post con etichetta database. Mostra tutti i post

martedì 8 ottobre 2013

Postgres su ZFS

Recentemente Oracle/SUN ha presentato una nuova generazione di storage appliance ZFS, la famiglia ZS3. Questi sistemi vengono proposti come piattaforma ideale per il dispiegamento di database (Oracle, ovviamente) grazie alle caratteristiche di ZFS, quali snapshot a caldo in tempo costante, clonazione degli spazi di storage, e gestione ultra sicura dei dati.
Effettivamente ZFS ha delle caratteristiche straordinarie, ed un paper dell'università dello Utah sottolinea come gli "scenari di disastro" che si propongono più comunemente nella gestione dei database, o le esigenze di testing e sviluppo siano gestite in modo particolarmente efficiente da ZFS.
Ispirato da queste considerazioni, ho creato una virtual machine con Oracle Solaris 11.1, su cui ho creato delle zones, ed installato Postgres. Ho fatto qualche piccola prova di management e replicazione di database, disaster recovery e clonazione e devo dire che la semplicità di gestione del tutto è straordinaria.
Morale? Credo che ZFS offra delle caratteristiche così interessanti, che nessun server possa ormai farne a meno. Inoltre esistono diverse distribuzioni di unix, tra cui i vari flavor di solaris (OmniOS, Illumos, Open Indiana, ecc...) e FreeBSD che offrono sia ZFS che zones o analoghi sistemi di light virtualization, che li rendono piattaforme ideali come NAS, database server, web server o application server, sia come sistemi di sviluppo, che testing che produzione.


mercoledì 17 febbraio 2010

Ubk

ubk is a framework that allows the web-developer to rapidly build up data-driven or data-based web-applications. Pages are written in an xml/xhtml dialect, rich of build-in tags made to loop through a result-set, show data in a variety of ways, easily navigate the db structure, reuse xml snippets, and so on. All of the application logic resides in pure php files, that can be used to manage lots and lots of xml-page-definitions with the same abstract logic, adding separation between application-logic and presentation. This version includes AJAX support via the (gorgeous) prototype library.


http://code.google.com/p/ubk/

ubk è un framework che permette agli sviluppatori di costruire rapidamente applicazioni orientate alla gestione dati. Le pagine sono scritte in un dialetto di xml, ricco di tag fatti per ciclare su un result-set, visualizzare i dati in vari modi, "vascare" facilmante la struttura del db, riutilizzare parti di codice xml, e via dicendo. Tutta la logica applicativa risiede in file php puri, che possono essere utilizati per gestire molti file xml che condividano la stessa logica di funzionamento, fornendo quindi la separazione fra logica applicativa e presentazione. Questa versione include il supporto per AJAX attraverso la (fantastica) libreria prototype.


http://code.google.com/p/ubk/



sabato 5 settembre 2009

Open source data modeling tool

Per un nuovo progetto su cui sto lavorando, ho iniziato ad utilizzare Power*Architect, un tool per il disegno dei database. Scritto in Java, si connette via jdbc al target db (e quindi anche a Postgres)... per questi primi giorni di utilizzo ho individuato un paio di problemini, ma probabilmente li risolveremo mettendo mano al codice open. Problema ben più grosso il fatto di non poter introdurre, in un unico diagramma, relazioni appartenenti a più schemi (problema risolto con un workaround, ma radicato nell'architettura del sw).
Appena Ubik tornerà dalle ferie, valuteremo con lui la possibilità di partecipare attivamente allo sviluppo, e dare una mano ai ragazzi canadesi ;)

mercoledì 29 aprile 2009

DbVisualizer 6.5.5

Utile! Connesso a un db Postgress permette estrarne il diagramma er!

lunedì 28 aprile 2008

Inheritance in SQL


While having a brief look at PostgreSQL, I saw a very interesting feature: table inheritance.
(Please refer to the documentation for a more precise description.)

This brilliant feature can lead to a very easy and efficient object to relational mapping!

lunedì 17 marzo 2008

db4objects: un db engine object oriented

db4objects è un engine db object oriented con doppia licenza (alla MySQL) disponibile in versione open e in versione commerciale ed è in grado di integrarsi con Java e con la piattaforma .NET.
Sembra disporre di tutto ciò che serve (transazioni, query language avanzato, sistemi per il supporto al refactoring) per lo sviluppo di applicazioni orientate ai dati di nuova generazione.
Staremo a vedere.

giovedì 6 dicembre 2007

Metodologia OO2R

Ecco un modello pratico per la realizzazione di infrastrutture di persistenza per applicativi modellati su architetture Object Oriented. Il prodotto di questo modello non e' un vero e proprio DB Object Oriented, ma consente di sviluppare strati di persistenza consistenti per sistemi OO, sfruttando nel contempo quelli che sono i punti di forza (prestazionali) dei database relazionali.



Caratteristiche architetturali

Nello strato di persistenza non vengono implementati i metodi delle classi, ma soltanto gli attributi. Non sara' quindi possibile effettuare query con chiamate a metodi direttamente in SQL, ma sara' necessario passare dallo strato del linguaggio OO per questo tipo di query, con una penalizzazione delle prestazioni. Occorre quindi porre attenzione all'analisi architetturale del sistema, tenendo conto del trade-off tra design e performance.

Poiche' il sistema e' suddiviso in due strati (lo strato Java e lo strato DB) e' necessario sempre tenere presente quando e in che modo in due strati sono coinvolti nelle varie operazioni, per poter offrire una buona stima delle prestazioni del sistema in progetti reali dove queste siano essenziali.

Cerchero' sempre di sottolineare l'esatto livello di coinvolgimento dei due strati, con una digressione sulle performance.



Prerogative dei database OO

Elenco qui le golden rules dei database orientati agli oggetti: per quanto possibile cercherò di sviluppare un sistema che ricalchi queste regole, e quando non sarà possibile rispettarle, indicherò le motivazioni.

  • Oggetti complessi

Deve essere possibile creare oggetti complessi aggregando oggetti più semplici; inoltre deve essere possibile applicare i metodi di aggregazione ortogonalmente . Questa feature verrà implementata tramite una relazione di aggregazione.

  • Object identity

A differenza del modello relazionale in cui l'identità di una entità è relativa al valore dei suoi campi chiave, in un db object oriented è necessario identificare un oggetto indipendentemente dal suo valore; questa feature verrà implementa semplicemente inserendo come chiave di ogni tavola che rappresenta un oggetto un campo objectId (che in MySQL sarà un Integer con Auto-increment)

  • Incapsulazione

In questo caso, poichè i metodi degli oggetti non vengono implementati dal DB, ma dallo strato Java sovrastante, l'incapsulazione è implementata dall'oggetto “Java side”

  • Tipi e classi

Anche in questo caso ci baseremo sulle feature di Java. Solo lo strato di persistenza verrà delegato al DB, attraverso tavole rappresentanti le entità del sistema

  • Gerarchia di classi

Naturalmente la “Java side” del sistema implementa nativamente le gerarchie di classi. Da un punto di vista dello strato di persistenza, la relazione di ereditarietà verrà implementata utilizzando come chiave primaria e objectId della classe figlia, una foreign key puntante all'objectId della classe padre. Le interfaccie (che sono prive di attributi e quindi prive di stato di persistenza) verranno implementate come tavole il cui unico attributo è l'objectId. Questo per permettere il polimorfismo nelle query.



Componenti del sistema

Livello di database

Il database prevede due metaclassi di componenti:

  • Entità

  • Relazioni

Da un punto di vista OO le relazioni rimangono invariate rispetto al modello relazionale, mentre cambiano le entità: inoltre nasce un tipo di relazione di ereditarietà, che va quindi correttamente codificata in SQL.

Livello del linguaggio (Java)

Per ogni classe di oggetti persistenti sono necessari due componenti:

  • La classe stessa (che implementa DataObject)

  • Un gestore della persistenza specifico



La metodologia

Il punto di partenza di questa metodologia è il class diagram del sistema, che -ATTENZIONE! - dovrà essere nella “versione per l'implementazione in Java” piuttosto che nella “versione dell'architettura implementabile in qualunque linguaggio OO”. Questo perchè in Java tutti gli oggetti derivano da Object. Se questa feature viene in qualche modo sfruttata, anche nello strato di persistenza ci dovrà essere una tabella “Object” che offre foreign key a tutte le entità del sistema! Naturalmente questa implementazione potrebbe non essere accettabile (potrei avere un numero eccessivo di oggetti nel DB, tale da impattare troppo sulle prestazioni e sullo spazio utilizzato su disco). Inoltre lo strato di persistenza deve includere anche gli attributi privati e protetti dell'oggetto da serializzare (che normalmente nei diagrammi dell'architetto non compaiono).

Ad ogni classe persistente corrisponde una tabella di tipo Entità nel database. Inoltre ogni entità ha un objectId (regola della Object Identity dei DB ad oggetti) che è anche la chiave primaria della tavola.

Qualunque tipo di relazione (ereditarietà [is-a], composizione [has-a], oppure user defined [abita-presso], [ha-il-permesso-per], ecc) viene rappresentata da una relazione – sempre una tavola del DB – con eventuali attributi.

La relazione di ereditarietà viene espressa tramite una chiave esterna utilizzata anche come primary key nella classe specializzata.



Esempio pratico

Prendiamo un diagramma UML:


Per il momento tralasciamo i particolari implementativi, ci interessa principalmente la struttura.

Un DocumentoVendita è una classe astratta, implementata da Fattura e Bolla, che ne implementano il metodo astratto stampa().

Inoltre aggiungono ognuno un attributi specifico di questa classe. D'altra parte abbiamo un'interfaccia RigaDocumento, e due classi implementanti, RigaFattura e RigaBolla, ognuna con le sue caratteristiche specifiche (che tralasciamo). Un DocumentoVendita contiene (usa) una collezione di RigaDocumento (la relazione potrebbe essere has-many).

Vediamo come possiamo implementare in Java questo modello, e come possiamo realizzarne lo strato di persistenza su un DB relazionale:


La classe astratta DocumentoVendita viene implementata dalla tavola documento_vendita, che oltre ad enumerare tutti gli attributi (attenzione! sia pubblici che privati!) della classe aggiunge come PK objectId, e come attributo normale objectRTTI. Il primo è un numerico con auto-incremento, mentre il secondo contiene il nome della classe reale (foglia nell'albero della gerarchia) dell'oggetto polimorfo. Questo secondo attributo è necessario soltanto nelle classi base. Lo strato di persistenza delle classi che ereditano da documentoVendita, viene implementato attraverso tavole (una per ogni classe implementante, quindi bolla e fattura). Queste tavole contengono gli attributi specifici delle classi ereditate, oltre a objectId. Quest'ultimo però, oltre ad essere chiave primaria, è anche foreign key sull'omonimo campo della tavola della classe base (documento_vendita), e non è auto-increment. Di fatto lo stato persistente di un oggetto fattura è dato dal join naturale tra “bolla JOIN documento_vendita ON (bolla.objectId = documento_vendita.objectId)”.

[qui manca una bella disquisizione sulla relazione has_many]

Ora supponiamo di dover estendere il nostro sistema, aggiungendo un ulteriore livello di specializzazione nelle fatture:

In particolare abbiamo aggiunto la classe derivata FatturaPersonalizzata.

Vediamo come adattare lo schema del DB:

La query per il data retriving di una fattura personalizzata:

SELECT *

FROM fattura_personalizzata JOIN fattura JOIN documento_vendita

ON (fattura_personalizzata.objectId = fattura.objectId AND fattura.objectId = documento_vendita.objectId)

WHERE fattura_personalizzata.objectId = ?

E' importante notare che anche con una elevata profondità nel grafo della gerarchia, le ricerche per objectId hanno sempre un costo estremamente limitato!



lunedì 27 novembre 2006

Method invocation in queries

In my object persistence engine I expect to be able to submit queries which can call methods on the stored objects:


SELECT Class c WHERE c.method();


Let's try to classify methods by their arguments, return values and side effects: the simplest kind of method I can use in a query is a “const” method (a method which doesn't modify the internal state of the objects) which returns a boolean and doesn't expect any argument. Such a method can be easily and safely be invoked during query execution, as it doesn't modify the object and is quite easy to evaluate. Methods that return something different from a boolean value, could cause problems during the evaluation of the WHERE clause. Also, methods expecting arguments could be difficult to evaluate as the query engine needs a mechanism to choose what argument to pass. But the most problematic type of method is the “non-const”, which modifies its internal state during the execution: this could require the query to re-evaluate some previously evaluated objects, or if the evaluated object modifies some other related object contained in the database could cause a cascade update, which could be difficult to handle. And, even worse, a method could throw an exception! But how to handle it?

  • Constness: if not const, could cause cascade modifications on the persistence layer
  • Return value: if not boolean (or primitive) could cause difficult evaluation
  • Arguments: if needed, could cause difficulties for the query engine to choose which
  • Exceptions: could cause difficulties in the execution thread

venerdì 24 novembre 2006

Object ID

9223372036854775807 is the maximum value of a Java long. It should be a sufficiently big number to be used for object identification in my ODBMS (well, actually it's an object persistence and query engine, but it could be used by a fully featured object oriented database management system in the future).
I'd like to be able to use consecutive numbers starting from 0 but I need an efficient hash function for indexing: the java.lang.Long's hashCode() won't do the work as it just returns a xor of the two halves of the value, so I was thinking about using something like this function - look for hash64shitf(long key).
Let's do some speed tests:
5 millions of hash values calculated with the hash64shit() took ~= 2450 mills, while the usual Long.hashCode() took 422 mills. Sure, the weak hash function is much faster, but 2,5 seconds for computing 5M hash keys is quite a small amount of CPU time!

giovedì 23 novembre 2006

Using the file system as a persistence engine for a database

I'm currently designing a sort of object oriented database engine in Java. I'd like to have a plug-in design for all the components, so that I can choose to implement them as I want. Now I'm thinking about the persistence engine, and I'd like to approach the problem with a different perspective; let's see what are the features I'd like to obtain from this component: first of all I'd like to implement it easily, then I'd like it to be enough performing to be usable not only for example purpose; I want caching, expandability, eventually replication and multi-volume. I've started thinking about an “ad hoc” file format, but its design is not so trivial: deleting records could cause an inefficient use of the space, and eventually fragmentation; and caching could be a nice problem too. Having to deal with this problems ain't that easy, which means that this approach could cause a big amount of time spent. So is there any thing able to perform this sort of operations efficiently? Sure: the file system! Modern file systems (have a look at Sun's ZFS ) do offer a lot, and they are virtually free, in the sense that any modern OS offers a set of features that include caching, mirroring, space saving features such as compression, and even security features such as journalling, error recovery and file content encryption.
So the choice is done, I'll think about a persistence engine based on the file system and directory structure (I could implement inheritance via subdirectory organization, and object reference with simple urls or links).

martedì 21 novembre 2006

Streaming applicato ad un DBMS

Recentemente ho utilizzato i servizi database in due modalita':
- In un modello client/server, con client e server dispiegati su due macchine diverse
- In un modello tipo Java EE (oppure Unify, per quelli che sanno cosa voglio dire..) dove DBMS e application server risiedono sulla stessa macchina (o cluster), e interagiscono con un client (o un terminare remoto) trasferendo le informazioni "un po' alla volta, tante quante ce ne stanno a video"

Nel primo caso esiste un limite tale per cui il risultato di una query e' di dimensioni tali da saturare la rete, il client si blocca in attesa del completamento del trasferimento del result-set (e quindi l'utente e' scontento), il DBMS fa fatica a processare altre richieste (la rete e' satura!) ed il sistema processore + memoria + disco del DBMS non lavora in modo efficiente.
In questi casi, potrebbe essere conveniente utilizzare una tecnologia di tipo streaming, o meglio un modello produttore/consumatore per il trasferimento dei risultati della query: il db trasferisce i risultati al client "man mano che li trova", mentre il client rimane in una condizione non bloccante su un buffer, e "consuma" i record man mano che arrivano. Inoltre il server potrebbe lavorare tenendo conto del consumo di record da parte del client, cioe' in caso di buffer vuoto, dare la precedenza alla query, mentre in caso di buffer riempito, diminuire la priorita' del thread, lasciando piu' risorse a disposizione di altri utenti.Pero' utilizzando questo approccio si perde la possibilita' di ottenere un result-set ordinato dal DBMS, tranne che in pochi casi particolari. Immaginiamo un DBMS ad oggetti, e pensiamo di poter passare un comparatore alla query per determinarne l'ordinamento:

SELECT Cliente c ORDER USING new Comparator<Cliente>() {
   int compare( Cliente a, Cliente b )
   {
      return a.indirizzo.compare(b.indirizzo);
   }
};

Ora la streaming query potra' essere ordinata se e solo se esiste gia' un indice basato sul comparatore, e il DBMS e' in grado di utilizzare questo indice. In caso contrario, se l'ordinamento deve essere fatto “al volo”, il DBMS dovra' prima ottenere tutti i risultati della query e poi ordinarli utilizzando il comparatore. Ma come fa il DBMS a capire se due comparatori (quello nell'esempio e' costruito “al volo”) sono equivalenti, cioe' possono utilizzare gli stessi indici? Un metodo protrebbe essere quello di mantenere all'interno del DBMS le istanze dei comparatori utilizzati, ed implementare un metodo di confronto tra comparatori:

interface Comparator<T> extends Serializable
{
   int compare(T a, T b);
   bool isEquivalent(Comparator b);
   int hasCode();
}

Con comparatori di questo tipo, il DBMS potrebbe creare gli indici man mano che i comparatori vengono utilizzati (eventualmente con delle statistiche di utilizzo, ed una euristica di rimozione dei comparatori e relativi indici non utilizzati), naturalmente deve manutenere gli indici quando vengono modificati i dati, ma ha la possibilita' di effettuare delle comparazioni tra comparatori (l'iterazione e' umana, la ricorsione e' divina!) e decidere di utilizzare indici di ordinamento gia' esistenti. Naturalmente se l'indice richiesto non e' presente, deve venire creato, allungando ulteriormente il tempo di esecuzione della query. Potrebbe essere buono per un applicativo dove le query si ripetono, ma decisamente dannoso in un datawarehouse.