sábado, novembro 11, 2006

Abstração de SGBDs - Estudo comparativo - Parte 1 Bibliotecas

Abstração de bancos de dados

Talvez você ache fácil comunicar-se com SGBDs no PHP através de funções específicas (mysql_connect(), mysql_query(), etc.). No entanto, talvez tenha percebido que um sistema recheado de “mysql_queries” perde muito em flexibilidade. Imagine o trabalho que o programador teria no momento em que precisasse passar a trabalhar com outro SGBD. E mais, imagine o grau de “retrabalho” no desenvolvimento de algum software com suporte a cinco ou dez SGBDs diferentes.
Mesmo que haja uma tendência a certa degradação de desempenho (degradação inclusive questionável, mas, a rigor, há esta tendência), seria interessante construirmos alguma camada de código capaz de intermediar as requisições particulares do sistema ao banco de dados que de fato foi utilizado. Apesar de nosso objetivo ser aprender o “como fazer”, nesse momento, não reinventaremos a roda. Existe uma série de bibliotecas a esse respeito.
Não seria bicho de sete cabeças desenvolver algo nesse sentido, entretanto, construir uma biblioteca de abstração de SGBDs realmente portável, isto é, capaz de trabalhar com pelo menos uns dez bancos diferentes, de maneira homogênea, suportando questões avançadas como prepared statements e transações e sabendo aplicar as particularidades de cada banco quando estas acarretarem ganhos de desempenho e segurança, pode sim ser uma tarefa complicada e trabalhosa.

Abstração de SGBD é uma necessidade absoluta?

Na verdade, a resposta é não. Como já dissemos, a tendência natural do uso dessa camada é a degradação de desempenho.
Diversas soluções nessa direção já foram desenvolvidas. Se você já trabalhou ou pelo menos ouviu falar na solução da Microsoft ODBC (Open Database Connectivity, baseada na Call Level Interface, CLI, da SQL Access Group), sabe que se trata de uma camada intermediária entre os processos da aplicação e do SGBD a fim de proporcionar essa portabilidade, uma vez que o programa só precisará acessar o driver ODBC que este último se encarrega da comunicação com o banco adjacente.
Acessar determinado banco através de um driver ODBC, no PHP (e porque não estender essa observação às demais linguagens), é normalmente mais lento e custoso para o servidor do que nativamente.
A própria Microsoft desenvolveu uma API para acesso a servidores de bancos de dados chamada ADO (ActiveX Data Objects), popular desde versões mais antigas do seu Visual Basic, que pode trabalhar via ODBC ou nativamente com alguns SGBDs. A sintaxe desta API inspirou diversas bibliotecas com o mesmo propósito no PHP, mesmo sob o olhar crítico de alguns que não gostam da ADO ou simplesmente levantam questões de incompatibilidade entre os dois ambientes.
Nossa opinião é a seguinte, se o desempenho for o requisito mais importante do seu sistema, acesse diretamente e se preocupe com os mínimos detalhes da API nativa do SGBD. No entanto, se a portabilidade e o conhecimento único aplicável a um grande leque de SGBDs forem questões relevantes no desenvolvimento de software, definitivamente, vale a pena investir na abstração.

Bibliotecas de abstração

Nessa seção, apresentaremos algumas das mais populares bibliotecas de abstração de SGBDs do mercado. Praticamente 100% dos programadores experientes em PHP utilizam ou já utilizaram alguma(s) delas em seus projetos, e isso certamente, lhes rendeu algumas horas de sono a mais.

Metabase
Uma das mais antigas ainda atualizadas e ativas no mercado. Criada por Manuel Lemos, desde quando o PHP ainda estava sua terceira versão. Mas muito bem adequada ao PHP4, ainda podendo ser utilizada em projetos PHP5 sem maiores problemas. No endereço http://www.phpclasses.org/browse/package/20.html, você encontrará sua mais nova versão, além de uma boa documentação em português.
Há três formas de interagir com suas funcionalidades. A primeira, mais antiga, é através de um punhado de funções que iniciam com a palavra Metabase, a segunda, através dos métodos de um objeto gerado pela função MetabaseSetupDatabaseObject, a terceira seria uma mistura das outras duas.
A tabela abaixo mostra a lista de SGBDs suportados pela Metabase e suas respectivas siglas utilizadas na biblioteca:

Tabela 1 – SGBDs suportados pela Metabase

Sigla

SGBD

ibase

Interbase

ifx

Informix

msql

Msql

mysql

MySQL

oci

Oracle

odbc

ODBC

odbc_msaccess

ODBC (particularmente ao Microsoft Access)

pgsql

PostgreSQL

sqlite

SQLite



É uma das bibliotecas mais preocupadas com a portabilidade. Com ela é possível modelar uma base de dados num arquivo XML e criar um script PHP para processá-lo e gerar o esquema no banco. Para isso, é necessário baixar um outro pacote, o Generic XML Parser, disponível no endereço http://www.phpclasses.org/browse/package/4.html.
Possui tratamento homogêneo a campos auto incrementados (que cada SGBD faz à sua maneira), funções de conversão de dados que possam sofrer mudanças de representação de um banco para outro como strings, datas, horas, pontos flutuantes e boleanos. Suporta consultas preparadas (prepared statements) e interage com tipos textuais grandes (CLOBs) e grandes binários (BLOBs) de maneira fácil e eficiente.

ADOdb
Disponível também para a linguagem Phyton, além de ser uma das mais antigas, é, sem dúvida, uma das mais populares do mercado. Nasceu da iniciativa de portar a sintaxe da Microsoft ADO ao mundo PHP. Suporta uma gama ainda maior de SGBDs como: MySQL, Interbase, Firebird, Oracle, MS SQL Server, Foxpro, MS Access, ADO, IBM DB2, SAP DB, SQLite, ODBC e, graças à sua imensa comunidade, PostgreSQL, Informix, Sybase, FrontBase, Netezza, ODBTP e ainda é capaz de acessar dados de um servidor de domínios LDAP.
Seu site oficial http://adodb.sourceforge.net/ cita diversos softwares populares que a utilizam, como os gerenciadores de conteúdo PostNuke, Xaraya e Mambo e a ótima solução de groupware eGroupWare.
Preocupa-se bastante com a portabilidade, como por exemplo, quando disponibiliza em seu objeto fruto da conexão métodos como SelectLimit(), para que você não escreva uma instrução SQL SELECT que contenha a maneira como o seu SGBD escolhido trabalha com consultas limitadas (LIMIT x OFFSET y, PostgreSQL, LIMIT y, x no MySQL ou SELECT TOP x *, no MS SQL Server, por exemplo), leftOuter(), rightOuter() e ansiOuter() para variações de JOINs entre tabelas e mais uma série de outros que você pode consultar no endereço http://phplens.com/lens/adodb/tips_portable_sql.htm.
Suporta ainda transações, prepared statements e, hoje, ainda é possível trabalhar semelhantemente à sintaxa da biblioteca PEAR::DB, que se popularizou bastante nos últimos anos. É possível utilizar recursos específicos do PHP5, como levantamento de exceções quando houver problemas na conexão com o banco, por exemplo. Apesar da pouca documentação nesse ponto, ainda há uma versão que você pode instalar como extensão do PHP, escrita em C, o que deve aumentar bastante o desempenho final.

DBX
Esta é a primeira iniciativa do PHP em criar uma extensão nativa e não um conjunto de arquivos PHP que devem ser incluídos no seu script. Totalmente procedural, apresenta algumas simples funções que fazem todo o trabalho. Suporta os SGBDs FrontBase, Microsoft SQL Server, MySQL, ODBC, PostgreSQL, Sybase-CT, Oracle (oci8), e, mais recentemente o SQLite.
É fornecida nas próprias fontes do PHP. Para habilitá-la, basta informar a diretiva --enable-dbx no momento de compilação. Com a recente extensão PDO, a DBX perdeu espaço, já que seu maior argumento, o fato de ser uma extensão do PHP, gerando uma API nativa (sem precisa dar include em arquivo algum), também se enquadra nesta última.

PEAR::DB
Até meados de 2006, foi um dos pacotes mais importantes do PEAR, visto que compunha a lista de pacotes básica inserida em qualquer distribuição do PHP. Rapidamente angariou inúmeros adeptos. Apesar de não ser a mais portável, nem tão pouco a mais eficiente (veremos um benchmark adiante), foi considerada a “oficial” do PHP por muito tempo, visto que mesmo sem ser uma extensão nativa, estava lá disponível em qualquer servidor Web que suportasse PHP.
Hoje, em seu endereço, http://pear.php.net/package/DB, há uma mensagem sugerindo que o programador opte por baixar o pacote PEAR::MDB2, já que sua última versão 1.7.6 será atualizada apenas para correção de bugs e ajustes de segurança. Provavelmente não passará de 1.7.X.
Trouxe para o PHP algumas técnicas bastante interessantes, como os métodos simplificados de recuperação de dados getAll(), getAssoc(), getRow() e getOne(). Suporta campos auto incrementados (sequences), prepared statements e transações. No entanto, alguns recursos como manipulação de BLOBs ficaram de fora. O endereço http://phplens.com/phpeverywhere/node/view/39 faz um comparativo entre a DB e a ADOdb. Apesar de tendencioso, dá para você fazer uma análise de que falta a essa biblioteca.

PEAR::MDB2
Sucessora de fato da PEAR::DB, a MDB2 é a segunda versão do pacote PEAR::MDB, uma iniciativa de portar a Metabase ao formato padrão do PEAR e aproximar da sintaxe da PEAR::DB. Apesar de (ainda) não ser distribuída na lista básica de pacotes PEAR, esta disponível através do comando pear install ou no endereço http://pear.php.net/manual/en/package.database.mdb2.php.
Por se tratar de uma adaptação da Metabase, a MDB2 vai bem mais além, em questões de portabilidade. Está certamente entre as que mais garante a pretendida abstração de SGBDs. Suporta, por exemplo, a manipulação de BLOBs e alguns outros recursos ausentes em sua antecessora.

Creole
Biblioteca interessantíssima não só pelo que faz, mas por como faz. No lugar de tentar se aproximar da sintaxe da Microsoft ADO ou da PEAR::DB, a Creole se aproxima bastante da sintaxe da API JDBC (Java Database Connectivity).
Surgiu como um subprojeto do Propel, um framework de mapeamento objeto x relacional. Devido à bagagem Java de seus desenvolvedores (o Propel possui algumas características do Hibernate, como mapeamento em arquivos XML), e à necessidade de uma API mais bem estruturada no mundo OO, em seu site oficial http://creole.phpdb.org/ consta a informação de que eles tentaram utilizar as bibliotecas PEAR::DB, PEAR::MDB e ADOdb, mas não ficaram satisfeitos com o resultado. Por isso criaram a Creole.
Possui ainda um outro subprojeto chamado Jargon, uma extensão que adiciona alguns métodos de atalho para leitura e escrita de dados.

PDO
Ex-pacote PECL (no PHP 5.0), a PDO é um dos recursos mais aclamados do PHP 5.1. Alguns acreditam que não passa de euforia passageira, afinal, ela não inventou nada realmente novo. O fato é que se trata de uma biblioteca, que por ser posterior, pôde ser arquitetada sobre os erros e acertos das demais. Alie isso ao fato da biblioteca vir na forma de extensão distribuída em conjunto com o PHP, o que sugere maior desempenho (acompanhe o benchmark adiante). Por outro lado, ela ainda precisa evoluir em portabilidade, nesse quesito ainda está bem aquém da Metabase, ADOdb, MDB2 ou Creole.
Suporta os SGBDs MySQL, PostgreSQL, MS SQL Server, Sybase, Informix, SQLite, Oracle, Firebird e MSSQL, além do ODBC, no entanto requer uma diretiva para suportar cada banco no ato de compilação. A linha abaixo configuraria o PHP para ser instalado como módulo do Apache2, com suporte aos SGBDs MySQL, PostgreSQL e SQLite, adicionando o acesso via PDO:

# ./configure --with-apxs2=/usr/local/apache/bin/apxs --with-pgsql=/usr/local/pgsql --with-mysql=/usr/local/mysql --with-sqlite --enable-pdo --with-pdo-pgsql=/usr/local/pgsql --with-pdo-mysql=/usr/local/mysql --with-pdo-sqlite

As barras invertidas acima servem apenas para poder continuarmos o comando na linha de baixo. Perceba que além de adicionar o suporte aos três SGBDs[1], habilitamos o PDO e inserimos uma diretiva para que ela seja capaz de acessar cada banco especificamente.
O site oficial http://www.php.net/pdo recomenda que você instale o PDO como um módulo compartilhado (shared), adicionando a diretiva da seguinte forma:

--enable-pdo=shared
Assim, um arquivo pdo.so será gerado no diretório da diretiva extension_dir do php.ini. Para habilitar o PDO, será necessário adicionar ao php.ini a linha:

extension=pdo.so
Como você faria no Windows para habilitar o pdo.dll que já vem fornecido na distribuição binária do PHP. O mesmo deve ser feito para cada SGBD (--with-pdo-mysql=shared e extension=pdo_mysql.so, por exemplo).
Num PHP já instalado, é possível adicionar o suporte ao PDO através do instalador do PECL. As linhas:

# pecl install pdo
# pecl install pdo_mysql
# pecl install pdo_pgsql
# pecl install pdo_sqlite
Irão disparar os mesmos passos do instalador pear. O único pré-requisito para esse procedimento é que o PHP tenha sido instalado com suporte à biblioteca Zlib (--with-zlib) para permitir que o pecl possa baixar e descompactar os pacotes do PDO. A instalação via pecl irá gerar o módulo compartilhado pdo.so (e os demais para cada SGBD adicionado) e você deve habilitá-los no php.ini da mesma forma da instalação shared. Nesses últimos dois processos é possível atualizar o pdo também através do pecl:

# pecl upgrade pdo
Instrução idêntica à que você faria para atualizar algum pacote PEAR.

1 SQLite não é um SGBD, mas um punhado de código C capaz de ler e escrever e um arquivo sob a semântica de acesso SQL. Assim como a PDO, já vem fornecido nas fontes do PHP.

5 Comentários:

Blogger Unknown disse...

teste

sábado, novembro 11, 2006 8:11:00 PM  
Anonymous Anônimo disse...

Artigo interessantíssimo, parabéns Felipe.

Sou desenvolvedor PHP há 5 anos, já conhecia a maioria dessas camadas de abstração, entretanto, a idéia da comparação foi genial, nos ajuda bastante no planejamento da aplicação.

quinta-feira, janeiro 18, 2007 4:55:00 AM  
Anonymous Anônimo disse...

Eu posso postar uma duvida com relação a PEAR DB ?
Grato,
Rogério.

terça-feira, março 27, 2007 10:59:00 AM  
Blogger Unknown disse...

Se eu souber, ajudo sim!

terça-feira, março 27, 2007 11:25:00 AM  
Anonymous Anônimo disse...

Muito artigo,

parabéns

quinta-feira, novembro 29, 2007 6:20:00 AM  

Postar um comentário

Assinar Postar comentários [Atom]

<< Página inicial