Sunteți pe pagina 1din 15

Caiuby Freitas

Caiuby Freitas atua profissionalmente na rea de consultorias e projeto e


desenvolvimento de softwares desde 1995. Possui ampla experincia em
OOP, Delphi e N-Tier.

Caiuby Freitas articulista e tem 4 artigos publicados (veja a relao).

Sexta-feira, 03 de junho de 2005


Datasets unidirecionais e bidirecionais

No por acaso que nos deparamos, freqentemente, com a seguinte


questo: o qu determina a qualidade do software que desenvolvemos?
Uma boa razo para isso que nem sempre encontramos uma resposta
definitiva.

Existem muitos fatores que podem influenciar na qualidade final de um


produto. Se nos detivermos um pouco nesta questo, certamente
encontraremos pelo caminho uma diversidade de conceitos,
metodologias e tcnicas que podem contribuir significativamente.

Contudo, ainda que possamos empregar um arsenal de ferramentas,


no devemos esquecer que, no final, um bom software depende de um
bom cdigo. Por isso, uma implementao descuidada de um excelente
projeto conceitual, pode transformar uma tima receita em um pssimo
produto.

Em vista disso, gostaria de conversar um pouco sobre o uso de datasets


unidirecionais.

Breve enfoque conceitual

Sempre que construmos consultas (queries), trabalhamos com a idia


de datasets. De um modo geral, os dataset funcionam como repositrios
temporrios de dados. Ns os utilizamos para armazenagem de
informaes (registros) provenientes de uma fonte externa, com
frequncia, de uma base de dados.

A estrutura de datasets tem por objetivo fornecer o suporte de software


para operaes de leitura, clculo, anlise e sada de dados.
exatamente isso o que acontece quando, por exemplo, ligamos a um
datagrid um componente TQuery. A partir da, temos condies de
visualizar dados, edit-los e navegar entre os registros retornados pela
consulta.

Este um recurso to fundamental que o utilizamos, seguramente, na


maioria das nossas aplicaes. At a, nada demais.

Do geral para o especfico

Porm, um detalhe importante que, por vezes, passa despercebido


que, em funo do conjunto de componentes que empregamos para
realizar operaes que manipulem datasets, trabalhamos,
convencionalmente, com um tipo particular, chamado de dataset
bidirecional.

O dataset bidirecional no o vilo da histria. Longe disso. Na verdade,


este o tipo mais verstil de dataset e, sem dvida, aquele que mais
utilizamos para possibilitar que nossos usurios visualizem os dados na
tela, efetuem buscas e editem registros.

O problema que nem sempre utilizado nas situaes apropriadas.


Explico: h uma srie de componentes que implementam este recurso
de maneira padronizada e, com isso, induzem o desenvolvedor
descuidado a generalizar seu uso, sem qualquer critrio.

A implementao de um dataset bidirecional prev o comprometimento


de um certo conjunto de recursos de memria. O que tem por finalidade
proporcionar a armazenagem temporria dos registros obtidos aps a
execuo de uma consulta qualquer base de dados.

Enquanto estes dados estiverem em memria ser possvel manipul-los


na tela (formulrio) ou atravs de mtodos anlogos a prior e ou next. De
modo simplista, podemos dizer que seu carter bidirecional se deve a
isso mesmo, quer dizer, possibilidade de navegarmos entre os
registros "de cima para baixo" e de "baixo para cima", em ambos os
sentidos, quantas vezes forem necessrias.

Numa situao apropriada, empregamos os dataset bidirecionais quando


queremos ter acesso a um conjunto de dados por um perodo indefinido
de tempo. Neste perodo, manipulamos, na verdade, uma "cpia" em
memria dos registros fisicamente gravados na base de dados. Embora,
til, pagamos um certo preo por isso.

O pulo do gato

Naturalmente, a alocao de memria efetuada pelo uso intensivo de


datasets bidirecionais tem impacto sobre o aspecto do desempenho do
software. Se pudermos medir este desempenho em razo do nmero de
situaes nas quais no precisaramos utiliz-los, teramos um
parmetro auxiliar para anlise qualitativa de rotinas realizam consultas.

Para combater o consumo desnecessrio de recursos de memria,


temos como alternativa o uso de datasets unidirecionais. Por sua vez,
este tipo de dataset no implementa qualquer procedimento de
armazenagem elaborado. Diferentemente, tem a finalidade de guardar
"cpia" dos registros apenas para procedimentos de anlise de
resultados e clculos. E, por esta razo, permite a leitura de dados "de
cima para baixo", uma nica vez.

O uso ideal de datasets unidirecionais se d atravs de rotinas que no


necessitem lig-los a componentes visuais, tais como datagrids. Seu
emprego se limita ao processamento interno de rotinas, nos quais o
usurio no pode intervir diretamente.

O pulo do gato consiste em distinguir claramente as situaes nas quais


precisamos apenas consultar e calcular dados, daquelas em que temos
a necessidade de reproduzir resultados em tela ou, ainda, permitir o uso
de recursos de navegao entre registros (prior e next). A propsito,
cabe mencionar que os datasets unidirecionais so tambm, read-only,
ou seja, no
possibilitam a edio de dados.
Por enquanto...

Nos limitamos aqui em ressaltar certos aspectos de implementao que


produzem efeitos sobre o desempenho e a qualidade do software,
motivo pelo qual apenas iniciamos a questo sobre o uso de datasets
unidirecionais e bidirecionais.

Daremos continuidade e aprofundamento nos prximos artigos. At


breve.
Caiuby Freitas
Caiuby Freitas atua profissionalmente na rea de consultorias e projeto e
desenvolvimento de softwares desde 1995. Possui ampla experincia em
OOP, Delphi e N-Tier.

Caiuby Freitas articulista e tem 4 artigos publicados (veja a relao).

Quinta-feira, 23 de junho de 2005


Datasets unidirecionais e bidirecionais - Parte 02

Ol Pessoal!

Nesta oportunidade vamos retomar questo na qual um bom software


depende, tambm, de um bom cdigo. Partimos do entendimento de que
podemos obter um ganho considervel de desempenho nas nossas
aplicaes quando no nos descuidamos de algumas tcnicas simples.

Sem dvida, este o caso dos datasets unidirecionais, j que


possibilitam uma economia de recursos de memria ao no manterem
cpia dos registros obtidos a partir de buscas em bases de dados.

Se, por um lado, verdade que esta funcionalidade implementada ao


custo de algumas limitaes quanto manipulao destes mesmos
registros, por outro, isso no chega a ser um empecilho, caso
identifiquemos corretamente as situaes nas quais o uso deste tipo de
dataset recomendvel.

No artigo anterior demos algumas dicas que podem orient-lo quanto a


tais situaes. Neste momento, iremos explorar a aplicao prtica deste
recurso.

Contextualizando

Os datasets unidirecionais no so exclusivos do ambiente de


desenvolvimento do Delphi. Ao contrrio, eles tm uma histria que nos
remete s primeiras tentativas de otimizao do desempenho de
interfaces para acesso a dados.

Sobretudo naquelas ocasies passadas, havia uma necessidade


imperativa de aliar crescente disponibilidade de dados, os recursos
computacionais limitados que restringiam o funcionamento de aplicaes
complexas.

No curso da evoluo do Delphi como um ambiente de desenvolvimento,


a Borland possibilitou a apropriao das solues encontradas atravs
de uma ampla gama de componentes dataware, capazes de
implementar alternativas diversas para conexo e manipulao de
dados.

At a verso 7.0, podemos contar, pelo menos, quatro grupos de


componentes dataware que facilitam o uso comum de datasets
unidirecionais. Estes grupos so representados pelas seguintes
interfaces: Borland Database Engine (BDE), Microsoft ActiveX Data
Objects (ADO), Provider de uso genrico e multiplataforma (DbExpress),
e Provider de uso especfico (InterbaseExpress ou IBX).

Cada uma destas alternativas trata do mesmo assunto de modo


diferenciado. Porm, todas, fundamentam nisto algumas importantes
questes de desempenho.

Da teoria prtica

Vamos examinar a maneira como cada uma destas interfaces fazem uso
de datasets unidirecionais.

Borland Database Engine

Originalmente a alternativa para integrao com base de dados da


Borland. Atualmente, descontinuado, mas ainda caracterstico da
plataforma-legado de um nmero considervel de aplicaes no
mercado. Fundamenta-se em uma arquitetura uniforme para bancos de
dados locais, baseados em arquivos Paradox e Xbase. Oferece
recursos de conexo via ODBC.

O mau hbito induz o desenvolvedor a programar consultas sem


configurar a propriedade UniDirectional do componente TQuery para
TRUE. O resultado desta omisso sempre pssimo quando se trata de
rotinas de checagem que no envolvam a vinculao a datagrids ou a
componentes conectados (*).

(*) um componente conectado aquele que mantm um vnculo direto


com o dataset. No Delphi, este vnculo estabelecido,
convencionalmente, atravs das propriedades Datafield e DataSource.

Microsoft ActiveX Data Objects

Como alternativa framework de acesso via ODBC do BDE, os ActiveX


Data Objects baseiam-se em um conjunto de objetos COM que acesso a
dados atravs de um provider OLEDB. Mais rpido e verstil incorpora
recursos de conectividade com Database Managment Systems (DBMS)
como, por exemplo, Oracle e SQLServer.

A configurao de datasets unidirecionais depende, neste caso, do


entendimento do conceito de cursores e de recordsets. Traduzindo em
midos, os cursores afetam a maneira como podemos navegar por um
conjunto de registros (recordset), assim como a visibilidade das
operaes de alterao de dados efetuadas por outros usurios.

Entre os tipos existentes, temos: ctOpenForwardOnly, ctKeyset,


ctDynamic e ctStatic. Destes, o que nos interessa o
ctOpenForwardOnly, dado seu comportamento unidirecional. Para utiliz-
lo basta configurar a propriedade CursorType do componente
TADOQuery.

Esta propriedade tambm est presente nos componentes TADOTable e


TADOStoredProc, porm menos usual.

Interbase Express (IBX)

Introduzidos pela Borland no Delphi 5, os componentes IBX tinham a


finalidade de aprimorar o projeto de conectividade com o Interbase
soluo de DBMS j bem conhecida que formatou as bases para uma
verso de cdigo aberto que surgiria mais tarde, a saber, o Firebird.

O IBX implementa mecanismos de conexo direta atravs de API do


Interbase o que, por si s e, principalmente em oposio ao BDE, sugere
uma arquitetura alicerada no imperativo de maior desempenho em
operaes de acesso a banco. Alternativamente, h um conjunto de
componentes dataware de cdigo aberto similares consulte IB
Objects.

Alm da otimizao do uso dos recursos de memria para manter


cpias dos registros ser configurvel atravs de componentes de
acesso bidirecional, que reduzem as operaes de releitura da base de
dados (fetches); o IBX conta com um componente que trabalha
exclusivamente com datasets unidirecionais: TIBSQL.

Providers de uso genrico e multiplataforma (DBExpress)

Os componentes do DBExpress conformam um conjunto de drivers de


alta performance para acesso a bases de dados diversas. A
conectividade garantida atravs softwares especficos para
comunicao (Dlls) com o DBMS que se deseja utilizar.

O interessante desta alternativa, alm das amplas possibilidades de


conexo, sua versatilidade multiplataforma consulte CLX e sua
arquitetura projetada para obter o mximo de desempenho com o
mnimo consumo de recursos de hardware e software.

Esta arquitetura introduz, explicitamente, os benefcios do uso prtico


dos datasets unidirecionais, indo muito alm da simples configurao de
propriedades em componentes dataware.

A funcionalidade deste tipo de dataset est presente na arquitetura de


todos dos componentes disponveis, conforme veremos.

Indo direto ao ponto, h apenas dois grupos de componentes


DBExpress:

01. que implementam datasets unidirecionais e,


02. que no implementam.

No primeiro grupo encontramos quatro componentes dataware:


TSQLDataSet, TSQLQuery, TSQLTable, e TSQLStoredProc. O uso
prtico destes recursos para obter melhor performance requer situaes
em que:

a) no sero necessrias operaes de navegao entre registros, como


as de ida e volta atravs de comandos prior e next;

b) no sero executados comandos de atualizao de dados (eles no


permitem edit ou post);

c) no sero utilizados filtros ou combos de look-up (aqueles que


buscam dados em outras tabelas).
Em troca destas limitaes, estes componentes oferecem alto
desempenho na busca de dados atravs de comandos SQL, visto que
no so sobrecarregados com funcionalidades nem sempre utilizadas.

Para todas as demais situaes a alternativa oferecida pelo DBExpress


resume-se um dataware: o TSimpleDataset, o nico (grupo 2) que
trabalha com datasets bidirecionais.

Por enquanto...

Ficamos por aqui com uma panormica sobre os recursos de


conectividade, disponveis na IDE do Delphi, que trabalham com o
conceito de datasets unidirecionais.

Retomaremos este tema em outra oportunidade atravs de exemplos,


com cdigo-fonte, que podero ajud-lo a medir os ganhos em
desempenho das suas aplicaes.

At breve.
Caiuby Freitas
Caiuby Freitas atua profissionalmente na rea de consultorias e projeto e
desenvolvimento de softwares desde 1995. Possui ampla experincia em
OOP, Delphi e N-Tier.

Caiuby Freitas articulista e tem 4 artigos publicados (veja a relao).

Quarta-feira, 27 de julho de 2005


Datasets unidirecionais e bidirecionais Parte 03

Nos artigos anteriores vimos que existem componentes dataware na


IDE padro do Delphi que possibilitam a utilizao de datasets
unidirecionais e bidirecionais.

Vimos tambm que as diferenas entre os tipos de dataset sinalizam a


possibilidade de aprimorarmos rotinas e melhorar o desempenho geral
de nossas aplicaes.

Tendo isto em mente, estamos munidos com tcnicas de fcil aplicao,


para identificar os gargalos no cdigo-fonte.

Nesta oportunidade, gostaria de ilustrar a questo explorando alguns


recursos especficos dos componentes dataware do DBExpress. A
escolha deste conjunto de ferramentas est fundamentada nas
peculiaridades de sua arquitetura, amplamente orientada para a
maximizao do desempenho em operaes de consulta e atualizao
de dados.

Camada de acesso

A camada de acesso a dados do DBExpress (DBX) foi modelada a partir


de um conjunto de classes que implementam apenas as funcionalidades
bsicas para integrao com softwares de gerenciamento de banco de
dados SQL (DBMS).

Sua versatilidade advm justamente disso: uma arquitetura simplificada,


que se baseia em interfaces padronizadas com suporte a drivers
especficos para a soluo de DBMS de sua preferncia.

Trocando em midos, isto significa:

1) reduo de instncias intermedirias para a troca de dados entre a


aplicao e o DBMS;
2) melhoria de desempenho em operaes de execuo de comandos
DML e DDL;
3) facilidade de instalao, atualizao e distribuio;
4) economia de tempo e de espao em disco.

S para se ter uma idia, enquanto os softwares que utilizam BDE


demandam cerca de 15 Mb para a instalao da camada de acesso a
dados e de ferramentas de configurao, o DBExpress requer apenas a
disponibilizao dois nicos arquivos: 1) um driver para comunicao
com o DBMS, 2) um arquivo para suporte a biblioteca do MIDAS; o que
representar cerca de 900Kb de instalao.
Todo o trabalho adicional de configurao pode ser feito a partir dos
componentes dataware inseridos na sua aplicao.

Modelo de classes

Oferecem suporte ao DBX oito classes fundamentais. Deste total, sete


so derivaes da classe abstrata TDataSet, a mesma que inclui
implementaes genricas de propriedades, eventos e mtodos tambm
compartilhadas pelo BDE, ADO e IBX.

Veja a figura a seguir.

At ai no h muitas novidades. O que vale a pena destacar, portanto, e


a maneira como o modelo de classes se organiza a partir da. As classes
TCustomSQLDataset e TCustomClientDataset, distinguem dois
grupos de componentes dataware e, levam at as ltimas
conseqncias, a idia de trabalhar com cursores unidirecionais e
bidirecionais.

Na prtica, todas as sub-classes derivadas de TCustomSQLDataset


gerenciam internamente apenas cursores unidirecionais. A exceo a
regra se d pela derivao de TCustomClientDataset que fornece
suporte a nica classe capaz de lidar com cursores bidirecionais na
arquitetura do DBX.

interessante notar que, neste modelo, o desenvolvedor sugestionado


a projetar sua camada de manipulao de dados, sempre a partir dos
conceitos que exploramos nos artigos anteriores. Assim, deste ponto de
vista, o melhor desempenho da aplicao passa a ser uma
conseqncia natural de todo processo de desenvolvimento.

Para execuo de comandos DML e DML podemos utilizar, de um modo


geral, os componentes TSQLDataset e TSimpleDataset. Estes
componentes funcionam como containers de todos recursos disponveis
e possibilitam trabalhar com queries, tables ou stored procedures.

No h nenhuma obrigatoriedade no uso do TSQLDataset, j que


dispomos tambm dos componentes mais especficos TSQLQuery,
TSQLStoredProc e TSQLTable. Entretanto, obrigatrio o uso de um
destes componentes caso queira tirar proveito do alto desempenho dos
cursores unidirecionais.

Quanto ao TSimpleDataset, podemos dizer que a ele cabe todas as


operaes que precisarem apresentar em ResultSets em tela,
propiciando ao usurio a visualizao e edio direta de dados. voc
pode, portanto, associ-lo a grids, campos de edio, combos etc.

Testes comparativos

Para demonstrar estes recursos nada melhor do que escolher uma base
de dados com uma considervel quantidade de registros.

O ideal seria trabalhar diretamente com DBMS como Oracle, MS-


SQLServer ou Firebird. Contudo, para simplificar um pouco, optei por
criar uma tabela (com dois campos) no Microsoft Access. Inseri 70.400
registros. Nenhuma otimizao foi feita atravs de ndices.

Para ficar mais interessante, as diferenas de desempenho dos


datasets unidirecionais e bidirecionais foram demonstradas atravs dos
mecanismos de acesso do DBX e ADO.

Por fim, como o DBX no possui um driver nativo para conexo, utilizei
um driver (dbxoodbc) de cdigo-fonte aberto disponvel gratuitamente
em https://sourceforge.net/projects/open-dbexpress.

No programa, foram utilizados os seguintes componentes:


SQLConnection, SQLQuery, SQLSimpleDataset, ADOConnection,
ADOQuery.
Veja abaixo como foram configuradas as propriedades dos componentes
dataware.

object ADOConnection: TADOConnection


ConnectionString =
"Provider=Microsoft.Jet.OLEDB.4.0;Data
Source=C:\Softwares\Delphi" +
"7\Projects\Performance\db1.mdb;Persist Security Info=False"
KeepConnection = False
LoginPrompt = False
Provider = "Microsoft.Jet.OLEDB.4.0"
Left = 80
Top = 200
end
object ADOQuery: TADOQuery
Connection = ADOConnection
CursorType = ctOpenForwardOnly
Parameters = <>
SQL.Strings = (
"SELECT * FROM TESTE")
Left = 80
Top = 240
end
object DBXConnection: TSQLConnection
ConnectionName = "Odbc Connect String"
DriverName = "openodbc"
GetDriverFunc = "getSQLDriverODBC"
LibraryName = "dbxoodbc.dll"
LoginPrompt = False
Params.Strings = (
"DriverName=openodbc"
"Database=exemplo"
"User_Name=sysdba"
"Password=")
VendorLib = "odbc32.dll"
Left = 152
Top = 200
end
object DBXQuery: TSQLQuery
MaxBlobSize = -1
Params = <>
SQLConnection = DBXConnection
Left = 136
Top = 240
end
object DBXSimple: TSimpleDataSet
Aggregates = <>
Connection = DBXConnection
DataSet.CommandText = "SELECT * FROM TESTE"
DataSet.MaxBlobSize = -1
DataSet.Params = <>
Params = <>
Left = 168
Top = 240
end

Segue abaixo o cdigo-fonte do programa.

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls,
Forms,
Dialogs, SqlExpr, DB, ADODB, StdCtrls, ExtCtrls, DBClient, SimpleDS,
ComCtrls;

type
TClock = record
startedAt, finishedAt : TDateTime;
end;
TConnType = (ADO, DBX);

TfrmTesteDesempenho = class(TForm)
ADOConnection: TADOConnection;
ADOQuery: TADOQuery;
DBXConnection: TSQLConnection;
DBXQuery: TSQLQuery;
grpTipo: TRadioGroup;
chkTipoDataset: TCheckBox;
Panel1: TPanel;
btnAvaliar: TButton;
log: TMemo;
Label1: TLabel;
DBXSimple: TSimpleDataSet;
pb: TProgressBar;
Label2: TLabel;
procedure btnAvaliarClick(Sender: TObject);
private
processStart : TDateTime;
clock : TClock;
connectionTime : double;
function conectar ( connType : TConnType ) : boolean;
procedure desconectar;
public
end;

var
frmTesteDesempenho: TfrmTesteDesempenho;

implementation

{$R *.dfm}

uses dateUtils;

function TfrmTesteDesempenho.conectar(connType: TConnType):


boolean;
begin
processStart := now;
result := false;
case connType of
ADO : begin
ADOCOnnection.open;
result := ADOCOnnection.connected;
end;
DBX : begin
DBXConnection.open;
result := DBXConnection.Connected;
end;
end;
end;

procedure TfrmTesteDesempenho.desconectar;
var
i: shortInt;
begin
for i := 0 to componentCount - 1 do begin
if ( components[i] is TCustomConnection ) then
( components[i] as TCustomConnection ).Close;
end;
end;

procedure TfrmTesteDesempenho.btnAvaliarClick(Sender: TObject);


var
elapsedTime : double;
begin
screen.Cursor := crHourGlass;
try
case grpTipo.ItemIndex of
0 : begin
DBXConnection.Close;
conectar ( DBX );
log.Lines.add ( "--- DBExpress -----------------------------" );
end;
1 : begin
ADOConnection.Close;
conectar ( ADO );
log.Lines.add ( "--- ADO------------------------------------" );
end;
end;
except
on e:exception do begin
screen.Cursor := crDefault;
showMessage( "A conexo no foi estabelecida" );
abort;
end;
end;
connectionTime := milliSecondSpan ( processStart, now );
log.lines.add ( "Conexo estabelecida s " + timeToStr ( processStart )
+
" em " +formatFloat ("00000.00", connectionTime )+"
ms.");
try
clock.startedAt := now;
pb.Position := 0;
pb.Min := 0;
pb.Step := 1;
pb.Max := 70400; //total de registros
case grpTipo.ItemIndex of
0 : begin
if ( chkTipoDataset.checked ) then begin
with DBXQuery do begin
sql.clear;
sql.add ( "SELECT * FROM TESTE " );
open;
while not eof do begin
DBXQuery.next;
pb.StepIt;
application.processMessages;
end;
end
end
else begin
with DBXSimple do begin
dataSet.commandText := "SELECT * FROM TESTE ";
open;
while not eof do begin
DBXSimple.next;
pb.StepIt;
application.processMessages;
end;
end
end;
clock.finishedAt := now;
end;
1: begin
with ADOQuery do begin
if ( chkTipoDataset.Checked ) then
cursorType := ctOpenForwardOnly
else cursorType := ctKeyset;
sql.clear;
sql.add ( "SELECT * FROM TESTE " );
open;
while not eof do begin
ADOQuery.next;
pb.StepIt;
application.processMessages;
end;
clock.finishedAt := now;
end;
end;
end;
elapsedTime := milliSecondSpan ( clock.startedAt, clock.finishedAt);
log.lines.Add( "Consulta executada em " +
formatFloat ( "0000000.00", elapsedTime) + " ms." );
finally
desconectar;
screen.Cursor := crDefault;
end;
end;

end.

Concluso

Neste artigo, pretendemos apresentar os conceitos fundamentais da


manipulao de datasets unidirecionais e bidirecionais vinculando teoria
prtica.

H muitas particularidades a explorar no que diz respeito aos


componentes do DBExpress que colaboram para ganhos ainda mais
considerveis de desempenho.

Vale a pena manter-se informado a respeito.

At breve.

S-ar putea să vă placă și