Dec 06

ADOdb es una librería de abstracción de base de datos para PHP muy potente. Dispone de una cantidad de usuarios y casos de éxito importante y ofrece muchas funcionalidades interesantes con soporte para una buena lista de engines de BD. Es un proyecto maduro, iniciado el año 2000, que si no conoces se merece una ojeada en su página oficial.

Como consecuencia de la cantidad de funcionalidades que ofrece es un layer tirando a lento (existen alternativas más rápidas y limpias). Esto es debido a que es un proyecto enorme con miles de lineas de código algunas de ellas, desgraciadamente, de no mucha calidad. Aunque a mi personalmente me gusta mucho y en todo proyecto software existen algunas partes un poco feas.

Dependiendo de la carga del site donde uses ADOdb o dependiendo de si necesitas todas sus funcionalidades es aconsejable estudiar bien otras alternativas mucho más lights. Como ADOdbLite (simulando ADOdb pero mucho más optimizada y con muchas menos funcionalidades), PDO (dispone de las características más importantes de ADOdb, es más rápida y se ha convertido en el estándar), PEAR MDB2 (sucesora de la clásica DB, potente y bastante rápida). Según John Lim, ADOdb no es que sea tan lenta, pero si la usas en un site con bastante carga y no realizas ninguna de las optimizaciones aquí descritas puedes estar perdiendo unos cuantos segundos en el total de una sesión de usuario (decenas o centenares de ms por página), y muchísimos más si entramos en el tema del uso de la cache de queries (que con esto ADOdb no es precisamente el culpable sino que proporciona un sistema de cache para el acceso a BD).

Es cierto que ADOdb arrasa en funcionalidades sobre las tres alternativas que he comentado pero como en muchas situaciones en el desarrollo en PHP vale la pena valorar las funcionalidades versus rendimiento. Estudiar bien el uso que le vamos a dar a la librería, la carga del site. frecuencia de las queries (dependiendo del tipo de web o de si disponemos de caches de contenido), etc.

Si a pesar de lo anterior te encanta ADOdb y lo quieres utilizar o si ya lo usas en algún proyecto y no puedes asumir un cambio, aquí van algunos consejos para mejorar el rendimiento del acceso a BD (optimizaciones para la librería y como usar la cache de queries).

[1] Usar la extensión de C de ADOdb. Si la instalas la librería PHP del ADOdb se encargará de usarla, aunque también puedes usar directamente las funciones adodb_* en tu código. Puedes descargarla aquí, dentro del archivo están las instrucciones para su instalación (archivo README.txt).

[2] Sobretodo, si tiras de la versión PHP de la librería usar un acelerador de código con opcode cache. Como APC o EAccelerator. Con sites con mucha carga, por mi experiencia personal, APC lo considero un sistema mucho más estable que el EA. El APC se instala como una extensión PECL del PHP.

[3] Usar la cache de ADOdb para tus queries. Esto se consigue con el uso de CacheExecute(). De las queries ejecutadas con este método se almacenan los recordsets devueltos a disco, esto es, con las siguientes queries idénticas el ADOdb devuelve el objeto serializado de disco hasta que no caduque.

Para poder usar CacheExecute() es necesario crear un directorio para la cache e iniciar el ADOdb como sigue:

[php] $ADODB_CACHE_DIR = ‘/var/directorio_para_la_cache’;
$db = NewADOConnection($dsn.’/’.$dbname);
$db->SetFetchMode(ADODB_FETCH_ASSOC); [/php]

Para lanzar una query almacenando cache durante un día:

[php] try {
$sql = ‘SELECT id FROM datos WHERE nombre=”‘.$n.'”‘;
$rs=$db->CacheExecute(86400,$sql);
// …
} catch (ADODB_Exception $e) {
// …
} [/php]

Contando claro que trabajamos con PHP5 y que hemos cargado el soporte para exceptions del ADOdb. Esto se consigue añadiendo:

[php] require_once ‘adodb/adodb-exceptions.inc.php’; [/php]

[4] Es interesante valorar memcached como sustituto de la cache a disco por defecto. ADOdb incluye el código necesario para usarlo. Memcached es teóricamente más rápido que el acceso a los recordsets serializados a disco, aunque la principal ventaja que ofrece es la reutilización de la cache entre distintos servidores.

Una vez instalado memcached, para iniciarlo:

# memcached -d -m 512 -l 127.0.0.1 -p 11211 -u www

Para iniciar el daemon con 512 MB de memoria escuchando sólo en localhost y corriendo como usuario www. Cambiar 127.0.0.1 por la IP de vuestro servidor tanto en el comando como en el código PHP que sigue, y www por el usuario que ejecute el Apache. Es necesario instalar una extensión PECL para trabajar con memcached.

Para iniciar ADOdb y indicar que queremos usar memcached para nuestros CacheExecute:

[php] $db = NewADOConnection($dsn.’/’.$dbname);
$db->SetFetchMode(ADODB_FETCH_ASSOC);
$db->memCache = true;
$db->memCacheHost = ‘localhost’;
$db->memCachePort = 11211;
$db->memCacheCompress = false;
$db->cacheSecs = 86400; [/php]

[5] Aunque bastante incómodo y en algunos casos peligroso (futuros ALTER TABLE) es más rápido acceder directamente a $recordset->fields mediante el ID numérico y fijar la variable $ADODB_FETCH_MODE = ADODB_FETCH_NUM.

[6] Finalmente podemos mirar de ejecutar los métodos _Execute() y _query() para lanzar nuestras queries. Estos son métodos mucho más crudos. _Execute() a diferencia de Execute() no emula binding, p.e. necesario para usar Prepare() si nuestra BD no lo soporta nativamente. Por el otro lado _query() si que es mucho más limitado, a parte de no emular binding tampoco devuelve recordset y no tiene debugging.

Con todo lo anterior podemos tener ADOdb bastante más optimizado aunque si tenemos un nuevo proyecto por delante quizás lo más aconsejable es usar PDO dado que todo apunta a que se convertirá en el estándar a seguir para el acceso a base de datos en PHP.

Acerca del tema de la cache de queries, sin ánimo de alargar más el post, sólo decir que es mucho más óptimo usar memcached para cachear objetos que no cachear las queries necesarias para generar estos objetos… si disponemos de unos buenos sistemas de caches de contenido (p.e. squid) y un sistema de cache de objetos genérico (memcached) cachear las queries deja de ser tan importante aunque te ofrece otro nivel de cache para jugar.

En un siguiente post dedicado a los sistemas de cache en PHP explicaré con más detalles como trabajar con APC y Memcached sobre servidores FreeBSD.

Tagged with:
preload preload preload