Archivos Mensuales: julio 2012

[Linux] De las comparativas (benchmarks) y otras justificaciones

Introducción

En un comentario anterior, el compañero Piccoro, hace una remembranza de unas pruebas de rendimiento que hiciera hace ya mucho Sun Microsystems  (antes que la comprara Oracle Corp.) sobre sus conocidos equipos SunFire, estas pruebas de rendimiento (conocidas como las “SPECjAppServer2004”) realizadas en 2007, ahora no están al alcance del público (aunque pueden aún ser encontradas en mi dropbox) pero demuestran el rendimiento de una misma aplicación, optimizada en estos equipos para Oracle, postgreSQL y MySQL.

¿Qué descubrimos con esta prueba?, veamos!.

La prueba Java (antes que fuera de Oracle)

MySQL 5 fué instalado en un equipo con las siguientes características:

  • Sun Fire X4100 (2×285,4x2GB,2X73GB) (2)
  • Sun StorEdge 3320, 12x73GB, 1 RAID CONT
  • Single-Port PCI Ultra320 SCSI HBA

Costo de la Licencia: 0$
Costo de implantación : 59.260 US$
MySQL: 720 JOPS

PostgreSQL 8.2 fué instalado con estas características:

  • Server HP Integrity rx2660 1.6Ghz 18GB 4-core (2)
  • 12GB DDR2 memory pair
  • SAN Array 1000

Costo de la Licencia: PostgreSQL 8.2 (0 US$)
Costo: 70.701 US$
Puntaje: 778 JOPS

Y Oracle 10g fué instalado con las siguientes características (semejantes a PostgreSQL)

  • Server HP Integrity rx2660 1.6Ghz 18GB 4-core (2)
  • 12GB DDR2 memory pair
  • SAN Array 1000

Costo de implementación: 70.701 US$
Licencias: Oracle 10g Enterprise + Oracle App Server + Oracle Partition Option
Costo en Licencias: 120.000 US$
Puntaje: 874 JOPS

Las pruebas, aunque en el mismo hardware físico gana Oracle (por al menos unos 70 puntos), demuestran que necesitas gastar 200US$ por unidad adicional para poder implementar Oracle, es decir, que con el costo *únicamente* de las licencias Oracle podrías incorporar 2 nodos más al cluster postgreSQL; qué, manteniendo la proporción de crecimiento, implementar un único servidor Oracle a 874 JOPS cuesta lo mismo que implementar un cluster de 3 nodos postgreSQL (ejecutandose a un rendimiento de 2334 JOPS).-

¿Cierto o falso?, queda a criterio del lector, la EULA de Oracle prohibe terminantemente la realización de pruebas y publicación de resultados sin su autorización, so-pena de recibir acciones legales, pero como yo no hice el benchmark! 😉

pero revisemos otro benchmark.

Cuándo VMWare decidió no publicar “malos benchmarks”

En una aclaratoria en su blog, la gente de VMWare explica que la clausula de la EULA (End-User License Aggrement) donde se prohíbe terminantemente la publicación de benchmarks de su producto versus otros productos de virtualización, no es porque “ellos estén en contra de las pruebas”, sino que le “sugieren amablemente” a las empresas encargadas de hacerlas, a que optimicen su producto y sólo utilicen el hardware que a “ellos” les es más conveniente, ¿interesante, no?.

Hace ya algún tiempo, la gente de specs.org publicaron una comparativa entre VMware ESX, la solución de virtualización para datacenters, y Linux KVM sobre Red Hat 6.1, resumiendo la conclusión:

KVM: SPECvirt_sc2010 1820 @ 114 VMs

VMWare: SPECvirt_sc2010 2721 @ 168 VMs

114 máquinas virtuales versus 168 es bastante, ¿no?, 900 puntos de diferencia en cuánto a rendimiento, también, ¿verdad?, pero, veamos a los detalles:

Primero, el equipo “sugerido” por VMWare para la prueba:

CPU: Intel(R) Xeon(R) X7560
Velocidad: (MHz) 2266
Núcleos: 32 cores, 4 chips, 8 cores/chip, 2 threads/core

Y el equipo con Red Hat:

CPU: Intel Xeon E7-2870
Velocidad: (MHz) 2400
Núcleos: Cores 20 cores, 2 chips, 10 cores/chip, 2 threads/core

El último es un simple HP Proliant Generación 7 (a un costo de 16800US$), el primero es un equipo ensamblado “especificamente” para VMWare, por su partner Bull Novascale, el “Novascale Bullion” fué catalogado como “el equipo para datacenter x86 más rápido del mundo” en 2011 y tiene un costo de 25 mil dólares la unidad.

Si a eso le sumamos la licencia de VMWare ESXi (9200 dólares por cada 2 núcleos), la cosa quedaría *más o menos* así:

KVM: Red Hat Licencias (Server=6500$ + Virtualización=6700) = 13200$
Servidor: 16800$
Total: 30000 US$
Costo: 263 dólares por VM (máquina virtual)

VMWare: Licencia=9200$ x 16 cores = 147200US$
Servidor: 25000 US$
Total: 172200 US$
Costo:  1025 US$ por VM (máquina virtual)

Entonces, ¿dónde está el rendimiento y el abaratamiento de precios?, además, hagamos algo bastante “jocoso”, reemplacemos Red Hat por Debian Linux (que el valor de siu licencia es “0$” – se lee cero!-) y te darás cuenta que por el mismo precio de la implementación de VMWare en tu empresa podrías pagar 11 servidores Proliant con GNU/Linux, ¡En vez de un equipo, tendrías un datacenter!  donde podrías en promedio (y según las cifras de Debian) virtualizar 990 máquinas virtuales.

A mí, me enseñaron que 990 VMs > (se lee, “es mayor qué”) 168 VMs, ¿no creen?.

Saquen ustedes sus propias conclusiones.

El Desconocido Gutenberg moderno

A mediados del siglo pasado, cientos de escritores de ciencia ficción, científicos y demás personalidades soñaban con al menos dos tipos de sociedades para el siglo XXI, una, alrededor de las fascinantes historias de “Amazing Stories” y extraordinarios inventos de Hugo Gernsback (cohetes, carros voladores y frecuentes viajes al espacio):

Otra, una sociedad distópica (como la predijo George Orwell), marcada por desigualdades insondables y por gobiernos que controlan a la población con ignorancia, basuras ideológicas y un “gran hermano” controlando la información (o desinformación) de la sociedad:

¿En cual sociedad creen que estamos?, ¿tenemos vehículos voladores?, ¿fusión nuclear en nuestros hogares?, ¿viajamos regularmente a Marte?, o ¿tenemos novelas distópicas para niños?, ¿nuestros gobiernos nos controlan hasta lo que aprendemos y “no aprendemos”?, ¿nuestros jóvenes conocen más de la basura de la moda y el “lifestyle” de ricos y famosos que de la vida de sus vecinos?, ¿en qué sociedad vivimos? …

¡Y las olimpiadas te presentan a …!

Me encontraba sentado en mi computadora, mientras de re-ojo veía la inauguración de los Juegos Olímpicos modernos “Londres 2012”, escuchando los comentarios de mi esposa, mi hermana, mi suegra y mi sobrina, suspiraban al ver a David Beckham, reímos disparatados ante la lluvia incesante de “Mary Poppins”  luchando contra Voldemort:

A veces sonaba alguna música de fondo y mi sobrina decía “Es Adele” o “mira!, Voldemort el de Harry Potter”; para una sociedad tan expuesta a la información (como lo muestra el sketch de “la red social” durante la inauguración de las Olimpiadas), me sorprende la cantidad de cosas que se sabe mi sobrina gracias al Internet, pero de repente y sin yo pensarlo, aparece una persona, sentada en su escritorio, con un computador (su viejo computador “NeXTCube” creado por Steve Jobs en 1990) y teclea lo siguiente:

This is for everyone.

Y aparece en su cuenta de twitter!:

¡Yo salto de mi silla y me postro en el piso en posición de reverencia!, gritando ¡Oh Grandioso!, ¡Oh, Grandioso!, a lo que saltan las dudas de mi esposa, mi suegra, mi hermana y mi sobrina, ¿Y quién es él?, preguntaron al unísono … y les grité:

“¡Es Tim Berners-Lee, el padre del World Wide Web!”

Y luego aparece magnífica la frase en todo el Estadio:

Y me preguntaba, ¿cómo la gente no puede saber quién es Tim Berners-Lee?, ¿Cómo se saben las canciones de Justin Bieber o los últimos escándalos de Lady Gaga y no saben quien es Tim?.

La cosa hubiera quedado en una simple “duda” que fué respondida a tiempo a mi familia, de no ser porque hoy he leído con preocupación cientos de amigos alrededor de la blogosfera, en todo el mundo, que les ocurrió la misma cosa …

Uno de ellos escribió:

Lo más lamentable, es que estoy bastante seguro, que el 90% de todas las personas “en el mundo” que vieron la ceremonia de apertura,no tenían ni la más remota idea de quien era ese hombre twitteando desde un computador” …

Capaz algunos pensaron que era Elton John u otra celebridad Inglesa Como Sthepen Fry o Mr. Bean, ciertamente, lamentable …

La sociedad de la desinformación

Es normal, vivimos en una sociedad de la “desinformación”, donde solo aprendes lo que te dice la “Mass Media”; donde la ingente carga informativa te desvía de las ideas primordiales del aprendizaje hacia una carga de “farándula” y “desconocimiento”; le sabemos hasta la última maña a Charlie Sheen o la última locura de Lady Gaga, pero desconocemos nuestros inventores y líderes modernos.

Esta persona, catalogada por muchos como el “Gutenberg moderno”, su implementación del protocolo HTTP y la creación del primer servidor Web por allá por 1990, creó la primera página web y se le considera el padre del World Wide Web, ¿cómo un hombre, que cambió la forma como conocemos el texto, ya no en libros sino en páginas electrónicas, páginas e imágenes electrónicas, sea tan desconocido?, gracias a su invento hemos dejado atrás al papel y la máquina de escribir gracias al libro electrónico, a las páginas web, al hipertexto.

Gracias a la masificación de la WWW la sociedad ha sufrido una revolución en la forma cómo nos comunicamos y como exponemos la información al mundo, sólo comparable a la época en que Johannes Gutenberg comenzó la revolución de la imprenta, y tal como Gutenberg, sus contemporáneos han ignorado a su inventor de una manera casi ridícula (hay que recordar que Gutenberg, el inventor de la imprenta moderna, murió en la indigencia, acogido en un monasterio).

Sin Tim Berners-Lee, no tendrías “Internet” (el 95% de las cosas que la gente hace en Internet son relativas a la WWW), ni correo web (el 90% de las personas no usan un cliente de correo), no tendrías Facebook, ni Twitter, ni Amazon, ni siquiera estarías leyendo este *blog* de no ser por ese incansable hombre, que una noche de Navidad de 1990, puso a correr el primer servidor web (CERN HTTPd) en la primera dirección web (http://info.cern.ch) viéndola en el primer navegador web (WWWeb), sin él, no estaríamos donde ahora estamos …

Notas Curiosas

Es extraño que Tim Berners-Lee siendo el precursor de movimientos como “La neutralidad de la red”, “la libertad de la información”, “redes de datos abiertos” y “la sociedad del conocimiento libre”, haya aparecido en la inauguración de las Olimpiadas de un país que arrestó por 2 años a un joven, acusado falsamente de terrorismo, porque publicó en Twitter que “iba a incendiar el aeropuerto” ya que estaba cerrado por huelga y no le permitieron abordar un avión para ir a visitar a su novia; personajes como Stephen Fry y el propio Berners-Lee lucharon contra la *Justicia* inglesa para que liberaran al joven.

¿Sabías qué luego de varias propuestas fallidas al gerente del CERN, Tim y su compañero Robert Cailliau trabajaron hasta tarde la noche del 24 y finalizaron la primera página web en la mañana de navidad del 25 de diciembre de 1990?.

Está NeXTCube de 1990 (la computadora personal de Tim en el CERN) fué el primer servidor web del mundo:

¿no les trae recuerdos a mis amigos sysadmins ese “letrerito” que dice “Esta máquina es un servidor, por favor NO APAGAR!!? … xD

En 1992 Tim tomó un viaje de 3 meses por USA, entre sus motivos estaba  conocer a Ted Nelson (El padre del concepto de Hipertexto, de la comunicación semántica y fundador del proyecto Xanadu en 1960, padre inspirador de las ideas de Berners-Lee), en su paso por el MIT, conoció a Richard Stallman, fundador del proyecto GNU y de la FSF, este, lo convenció que los conceptos construidos alrededor de la WWW (HTTP, Hypertexto, HTML, libwww, CERN HTTPd y el navegador WWWeb) fueran de dominio público, para que todo el mundo lo conociera, lo compartiera y lo mejorara, gracias al apoyo del MIT se logra además la creación de la W3 Consortium (W3C).

¿Sabías que Tim Berners-Lee no es informático?, bueno, realmente no “era”, era un físico asignado a problemas computacionales del CERN, tiempo después obtuvo su maestría en ciencia computacionales en el MIT.

Los padres de Tim Berners-Lee son famosos en Inglaterra por ser las primeras personas en dedicarse a la fabricación comercialmente viable de la primera computadora (en 1960, unos 20 años antes que Steve Jobs).

¿Sabías que esta fué la primera página web publicada en la historia? > TheProject

¿Sabías que Tim Berners-Lee pidió disculpas públicas por los doble-barra (slashes) en las direcciones web?, aunque le pareció una buena idea crear direcciones web (URL) con la asociación de las dobles barras de los servicios de red UNIX, pudo haberlas construido sin usarlas y se dió cuenta que era “innecesarias” mucho tiempo después.

¿Quieres una sociedad donde soñemos con web designers como Mark Suppes, que construyen reactores de fusión en el techo de su casa?

Si!, el reactor de arriba es hecho por un joven diseñador gráfico (trabaja como diseñador web para la tienda Gucci) que es entusiasta de la física teórica y diseñó un reactor Polywell-Farnsworth basado en las teorías de Bussard.

Entonces deja de pensar en el cumpleaños de Justin Bieber o en el color de las pantaletas de Lady Gaga y comienza a interesarte un poco más por ese conocimiento libre que te brinda tu mundo! …

Notas Finales

Acá les dejo dos artículos bastante interesantes, la primera, “Respuestas para gente joven”, un escrito de Tim Berners-Lee para preguntas básicas que le han hecho algunos niños y este video, de su última charla en las TED Talks, donde nos habla de los “datos abiertos” y la “neutralidad de la red”:

[postgreSQL] Una instalación de postgreSQL básica (¡pero mejor!)

PostgreSQL: Introducción

PostgreSQL es una de las grandes maravillas del software libre, robusto, potente, altamente funcional, distribuido en miles de formas posibles (greenplum=clusterizador masivo, postgres Plus=”imitador” de Oracle,deepgreen=granjas de datawarehousing con postgreSQL, etc) puede ser optimizado (como todo lo que es software libre) de maneras inimaginables para cada necesidad específica. Entonces, ¿por qué hay gente que denigra de él? …

El primer error que comete la gente, es pretender que un sistema tan necesario como la base de datos, sea utilizado “directamente” luego de su instalación; un detalle de distribuciones Linux como Debian, es no optimizar para ningún aspecto (ya que son meta-distribuciones genéricas sin una orientación específica).

Mientras Oracle saca libros de 900 páginas de cómo optimizar al máximo hardware, sistema de archivos, sistema operativo y la base de datos como tal, mucha gente piensa “migrar” a postgreSQL ejecutando un “aptitude install postgresql” y dejándolo así … nada más perdido y lejos de la realidad.

Acá, ejecutaremos una instalación que debería ser “básica”, la más básica, para un entorno pequeño de datos, para que sus sistemas “rindan”.

Preámbulo

Uno de los aspectos más importantes es que postgreSQL “no debería” compartir acceso a disco con el sistema operativo, esto es, si es posible que postgreSQL esté en una partición distinta a “root” (incluso un disco separado, de ser recomendable); por lo que la opción “instalar y usar” no debería ser para instalaciones en producción de postgreSQL 9.1.

Hay que tomar en cuenta que postgreSQL (como cualquier otra base de datos) debería ser optimizada posteriormente a su instalación de manera correcta, una de las optimizaciones más necesarias (pero que casi nadie sigue) es gestionar los espacios de datos y separarlos del tablespace pg_default (que gestiona la DB “postgres”, la DB de “information_schema” y demás información, por lo general en “/var/lib/postgresql/9.1/main”); además, ambos deberían estar separados de la partición raíz donde está el sistema operativo.

Las optimizaciones acá realizadas son de las más sencillas a nombrar para postgreSQL, se tomó una máquina virtual en Xen 4.1 en una portátil y se optimizó de lo más básico, para demostrar, que hasta en los cambios más sencillos, pueden afectar el “performance” de aplicaciones diseñadas con postgreSQL.

Preparación primaria

Si estamos instalando un servidor de datos, lo primero que debemos pensar es en separar el montaje de /var del resto del sistema, de hecho, si podemos incluso separar /var/log sería muy apropiado; también es bueno separar /tmp (más 1Gb es innecesario) ya que si no separamos /tmp, Debian GNU/Linux utilizará un tmpfs montado en RAM para gestionar /tmp (restándonos un poco de RAM para trabajar, además que postgreSQL no utiliza la partición /tmp).

Un esquema básico podría ser:

  • / (raiz) (Debian GNU/Linux no ocupa más de 5Gb en este modo)
  • /tmp (1Gb como máximo)
  • swap (Lo necesario, aunque no mayor a 2GB en sistemas con más de 4Gb de RAM)
  • /var (2~4GB ya que será un servidor en producción)

Y de resto, un volumen lógico (LVM) que podemos modificar de tamaño de acuerdo a nuestra necesidad.

Luego de instalado el sistema, procedemos a instalar PostgreSQL.

Instalación

La instalación de postgreSQL 9.1 en Debian GNU/Linux es bastante sencilla:

  • Instalamos postgreSQL 9.1 (pero así no se debería quedar):
    apt-get install postgresql-9.1

PostgreSQL por defecto, creará una carpeta de configuración en: /etc/postgresql/9.1/main/

Y creará un espacio de datos en: /var/lib/postgresql/9.1/main/

Que no utilizaremos para nuestra base de datos, ya que crearemos un espacio propio.

Configuración inicial

Siempre es recomendable dejar el usuario “postgres” (el super-usuario de PostgreSQL) como un usuario “para accesos de emergencia”, ya que este usuario tiene garantizado el acceso a todas partes(si eres root en el sistema), es recomendable que NINGUNA base de datos tenga como “owner” el usuario postgres (y evitar en lo posible utilizarlo como usuario de acceso desde sistemas, aunque esto, obviamente lo he visto más de una vez ocurrir hasta en sistemas web).

  • Creamos un super-usuario para nuestras necesidades, primero cambiamos al usuario postgres:
    su postgres
  • Creamos un usuario, que será nuestro “super-usuario” para “nuestros” accesos, evitando así el usuario postgres:
    createuser -sPl jesuslara
    
    -- ingresamos nuestra contraseña
    Enter password for new role: 
    Enter it again:
  • Ejecutamos la consola SQL de postgreSQL:
    psql
  • Garantizamos al usuario que creaste acceso irrestricto sobre el la DB postgres:
    psql (9.1.3)
    Type "help" for help.
    
    postgres=# grant all on database postgres to jesuslara;
    GRANT

Y salimos de la consola:

postgres=#\quit

Configuración de postgreSQL

  • Accedemos al directorio /etc/postgresql/9.1/main
    cd /etc/postgresql/9.1/main
  • Si vamos a acceder de manera remota a nuestro postgreSQL, agregamos la siguiente línea al archivo pg_hba.conf:
    # la forma es:
    # host -> database (all: todas las db) -> usuario (all: todos los usuarios) -> subnet (de nuestra red) -> modo de clave
    host    all     jesuslara       192.168.100.0/24        md5
  • Habilitamos el acceso remoto en nuestro postgreSQL:

archivo /etc/postgresql/9.1/main/postgresql.conf

listen_addresses = '*'

Optimización del archivo postgresql.conf

  • Y cambiamos algunas opciones básicas del archivo postgresql.conf:
    shared_buffers = 256MB

‘shared_buffers’: Es la memoria de trabajo compartida para todo el servidor postgreSQL, fíjese que por defecto en Debian GNU/Linux la opción es 24MB (y el valor por defecto si comentamos es 32MB), sin embargo, como esta es la memoria utilizada para trabajo de postgreSQL, es recomendable “al menos” el 25% de la RAM disponible (y jamás > 40%).

temp_buffers = 16MB

‘temp_buffers’: La memoria temporal utilizada por cada sesión para las tablas temporarias y para apertura de tablas en cada sesión de cada base de datos, tome en cuenta que este valor dependerá obviamente de la cantidad de datos que carga cada sesión y dependerá muchísimo del sistema que se utiliza.

work_mem = 16MB

‘work_mem’: uno de los valores más importantes y más despreciados, “work_mem” se refiere a la memoria temporal utilizada por cada sesión, para las operaciones de ordenamiento (ORDER BY) para las sesiones de diferenciación (GROUP … HAVING y DISTINCT) y para la gestión de hash (uniones HASH, indices HASH, hash_aggregations), si en nuestro sistema realizamos muchísimas consultas ordenadas, agrupadas, diferenciadas por cadenas, etc se crearán mucho de estos buffers de manera paralela, mientras más memoria asignemos, menos probabilidades hay que los ordenamientos y otras operaciones se hagan con archivos temporales en disco (más lentos que la memoria RAM).

max_stack_depth = 8MB

‘max_stack_depth’: define el tamaño del espacio utilizado para cómputo de operaciones complejas, su valor está asociado al límite máximo que un usuario (en este caso, “postgres”) tiene derecho a reservar un stack, el valor soportado por nuestra distribución se determina con “ulimit -s”.

shared_preload_libraries = '$libdir/plpython2.so'

‘shared_preload_libraries’: Permite cargar una librería específica cuando arranca el sistema, si utilizamos muchos procedimientos almacenados en un lenguaje específico (ej: python, perl, tcl, java, etc), es bueno pre-cargarla para que esté disponible cuando se utilice por primera vez. Nota: esta opción ralentiza un poco el reinicio del sistema.

bgwriter_delay = 500ms

‘bgwriter_delay’: El background-writer es un proceso del servidor que se encarga de escribir a disco todos los “shared_buffers” modificados, este proceso conlleva una carga de I/O sobre el disco, su modificación permite o reducir el valor para evitar en lo más posible pérdidas de datos en equipos que pueden fallar, o su incremento permite reducir el I/O al disco duro en sistemas perfectamente protegidos.

Modificados estos parámetros básicos, vamos a modificar nuestro sistema operativo.

Optimización de Linux para postgreSQL

Una de las cosas que olvidamos “optimizar” (tunning) es nuestro sistema operativo GNU/Linux, con grupo de valores en el sysctl ya podemos ayudar “mucho” a nuestro postgreSQL.

  • Agregamos al archivo sysctl.conf

archivo: /etc/sysctl.conf

kernel.sem = 100 32000 100 128
kernel.shmall = 3279547
kernel.shmmax = 289128448
kernel.shmmni = 8192
fs.file-max = 287573
vm.dirty_bytes = 67108864
vm.dirty_background_bytes = 134217728

Nota: observe el valor de shmmax, la cantidad de “memoria máxima reservada para un shared_buffer” que puede crear una aplicación debe ser igual o mayor al valor del shared_buffer de postgreSQL, este valor está en bytes y es ~ 275MB.

La cantidad máxima de archivos que pueden abrirse en un sistema, dependerá obviamente del nivel de trabajo de la DB, durante una operación regular, la gente puede ejecutar “lsof | wc” para obtener la cantidad de archivos abiertos.

  • Y luego, las aplicamos:
    sysctl -p
    
    --
    kernel.sem = 100 32000 100 128
    kernel.shmall = 3279547
    kernel.shmmax = 289128448
    kernel.shmmni = 8192
    fs.file-max = 287573
    vm.dirty_bytes = 67108864
    vm.dirty_background_bytes = 134217728

Ya, con estos sencillos cambios, podemos reiniciar el postresql:

/etc/init.d/postgresql restart
Restarting PostgreSQL 9.1 database server: main.

Y estamos listos para crear una partición y tablespace para nuestra DB.

Creación del espacio de tablas

Creamos una partición del tamaño necesario para contener “al menos” nuestra base de datos (esta es una guía básica, no hablaremos de particiones adicionales para metadatos, para índices y demás).

Nota: en nuestro caso, la partición es /dev/xvdb1 y mide 10GB.

El “journal”, para quien no lo conoce, es la razón por la cual no existe software de “desfragmentación” en Linux, todos los sistemas operativos que lo soportan (ext3, ext4, jfs, reiserfs, xfs, zfs, etc) tienen servicios que se encargan de ordenar, desfragmentar y gestionar tanto la data como los metadatos (información acerca de los archivos y carpetas en sí), pero además, los journal cumplen otras funciones, entre ellas, recuperar desde sus logs la data que pudiera “haberse perdido” luego de un fallo de energía y/o de sistema.

En sistemas de base de datos, la data es contenida en uno o más (y diversos) tablespaces, espacios de tablas donde la data, metadata e índices es contenida, como es la base de datos la encargada de gestionar la posición de los datos en ellos, el Sistema Operativo no requiere la presencia de un journal, o al menos, de un journal más relajado y menos estricto.

Formateando la partición

  • Se formatea la partición (disco):
    mkfs.ext4 -E stride=32 -m 0 -O extents,uninit_bg,dir_index,filetype,has_journal,sparse_super /dev/xvdb1

Utilizamos ext4, porque en modo “writeback” tiene un mayor performance que XFS para almacenar los tablespaces y tiene menor propensión a fallos.

  • Habilita el journal en modo writeback:
    tune2fs -o journal_data_writeback /dev/xvdb1
  • Si simplemente desea eliminar el journal, ejecute:
    tune2fs -O ^has_journal /dev/xvdb1
  • Nota: utilice esta opción a su propio riesgo, recuerde que no tener un journal afecta de 2 modos:
  • La data no es colocada en orden en el disco, fragmentando el mismo
  • Ante un fallo de energía, el FS no podrá recuperar desde el journal las últimas actividades para recuperar esos datos.
  • Se ejecuta un chequeo de archivo básico:
    e2fsck -f /dev/xvdb1
  • Creamos la carpeta de postgresql:
    mkdir /srv/postgresql
  • Y luego se monta con las opciones que describiremos más abajo:
    mount -t ext4 /dev/xvdb1 /srv/postgresql -o  noatime,nouser_xattr,noacl,discard,nodelalloc,data=writeback,barrier=0,commit=300,nobh,i_version,inode_readahead_blks=64,errors=remount-ro

Las opciones son:

Opciones de FS Linux:

noatime

No guardar la información del timestamp del último acceso a los archivos, esta información no es necesaria ya que postgreSQL gestiona apropiadamente el acceso a los tablespaces.

nouser_xattr

Deshabilita el uso de atributos extendidos de usuario, esto es seguro en postgreSQL ya que la carpeta donde se guardan los tablespaces no requiere ninguno de esos atributos.

noacl

No utilizar atributos extendidos ni ACLs POSIX, no son necesarias ya que solamente postgreSQL tendrá acceso a los archivos en esta partición.

Opciones específicas de ext4:

nobh

ext4 asocia buffers de datos con las páginas de datos, esos bloques de cache proveen garantía de ordenamiento de los datos; “nobh” evita el uso de estos buffers de ordenamiento de datos (sólo activable con “data=writeback”).

data=writeback

No se preserva el ordenamiento de los datos, la data será escrita en el sistema de archivos solo después que la metadata ha sido guardada en el journal. Aunque hay personas que recomiendan desactivar el “journaling” del disco, esto no es recomendable pues, aunque postgreSQL gestiona correctamente los datos, los metadatos (información de los archivos y carpetas en el FS) es responsabilidad de mantenerla consistente el FS.

commit=seconds

Los datos y metadatos son escritos a disco cada “n” cantidad de segundos, el valor por defecto son 5 segundos (commit=0 es igual a dejar el valor por defecto), un valor más bajo puede mejorar la seguridad de los datos, un valor muy alto mejora el performance pero ante un fallo podría perderse datos.

barrier=0

Deshabilita el uso de barreras de escritura, las barreras de escritura fuerzan el uso de ordenamiento on-disk de los commits al journal, haciendo las caché de disco seguras de usar, pero un daño en el performance del disco.

inode_readahead_blks=n

Cantidad de inodes que el sistema de pre-lectura de ext4 lee al buffer caché, el valor por defecto de n es 32, pero un valor de 64 es normal para optimizar las lecturas.

discard

Permite decidir que realiza con los bloques que son liberados, por lo general ext4 ejecuta una operación de trim (limpieza), con esta opción, ellos simplemente son marcados como descartados, evitando la escritura innecesaria de bloques.

i_version

Permite indicar que los inodes serán de 64-bits, solo disponible si se está en un sistema a 64 bits.

  • Luego de montada de esta manera, lo fijamos en el /etc/fstab
# particion para postgresql
/dev/xvdb1 /srv/postgresql ext4 rw,noatime,errors=remount-ro,nouser_xattr,noacl,commit=300,barrier=0,i_version,nodelalloc,data=writeback,inode_readahead_blks=64,discard 0 0
  • Comprobamos:
    mount -a

Y ya estamos listos para crear el espacio de datos para nuestra DB!.

El espacio de tablas (tablespace)

Crearemos un simple espacio de tablas en nuestro optimizado sistema de archivos ext4 para contener nuestra base de datos:

  • cambiamos el propietario a la carpeta /srv/postgresql
    chown postgres.postgres /srv/postgresql
  • cambiamos al usuario “postgres” y abrimos la consola ‘psql’:
    su postgres
    psql
  • En la consola, ejecutamos el comando para crear un espacio de tablas:
    postgres=# CREATE TABLESPACE db_sistema OWNER jesuslara LOCATION '/srv/postgresql';

Y listo!, ya tenemos un espacio de tablas disponible para crear bases de datos y optimizado!

Usando el espacio de datos optimizado

Para crear una DB que no esté asociada al espacio “por defecto” (pg_default) ejecutamos:

  • Crear una DB:
CREATE DATABASE sistema WITH ENCODING='UTF8' OWNER=jesuslara TEMPLATE=template0 TABLESPACE=db_sistema;

Y como verán, le pasamos el tablespace “db_sistema” que hemos creado anteriormente.

¿Alguna prueba de la eficiencia?

La configuración siguiente no se hizo en un sistema dedicado para tal, se realizó en una portátil, corriendo Xen 4.1 y en una VM con 1GB de RAM se instaló el postgreSQL con las opciones nombradas, sin embargo, es posible notar una mejora en el performance general de las consultas (y eso que son solamente optimizaciones básicas).

Para ello, creamos una DB adicional, de un sistema administrativo (migrado desde Oracle hasta postgreSQL) que un amigo amablemente me facilitó para esta prueba.

Para ello, se movieron algunas funciones de código “Visual Basic” a código PL/Python y PL/pgSQL y se creó una consulta semi-compleja, de unas 26 líneas de extensión, que unifica unas 6 tablas del sistema para calcular una simple pre-nómina (ivss, paro forzoso, caja de ahorros, faov, isrl, etc); hay que notar que en la versión “cliente-servidor” de la aplicación, la nómina de 13 mil empleados dura varias minutos hasta horas con múltiples conceptos; para nuestra versión “simplificada” (5 asignaciones y 3 deducciones y cálculo de salario integral); la consulta se ejecutó en: 33068ms Para 13674 registros.

Pero, lo mejor ocurre si lo ejecutas por segunda vez!, ya que los buffers de trabajo mantienen en cache las operaciones de hash_aggregate (necesarias para algunos de los cómputos de agregado realizados), la segunda ejecución fué: 3107 milisegundos (3 segundos)

¿13 mil cómputos de empleados en 3 segundos?, ¡Nada mal para ser una portátil!

Conclusiones

Estas optimizaciones no son ni la décima parte de las que podemos optimizar de postgreSQL, pero es un comienzo, esta guía surge de la necesidad de orientar a las personas, que creen que pueden poner un sistema en producción de un postgreSQL recién instalado, estas optimizaciones mínimas, que cualquiera puede seguir, son un ejemplo y un comienzo.

No se dejen engañar con esas personas que dicen que “postgreSQL no rinde como Oracle” y un largo etcétera de excusas baratas, si alguien en su sano juicio instala Oracle cambiando parámetros en el sysctl, modificando los valores de tunning del sistema operativo o del sistema de archivos, clusterizar al máximo e incluso hace cosas más “malandras” como generar índices “al vuelo” por aquellos DBA vagos que jamás piensan bien sus bases de datos; ¿por qué la gente no hace lo mismo con postgreSQL?, tal vez porque ser un DBA “certificado postgreSQL” es más difícil y hacer entender a la gente, cuando crean un sistema conectado a datos, que su principal preocupación no debería ser “si usar PHP o Python” sino ver de qué formas optimizarás el S.O, el sistema de archivos, las consultas, el planificador, el acceso a disco y la gestión de índices para lograr que te sea “inocuo” si la gente utiliza perl o Visual Basic como Front-End.

Al final, postgreSQL debe tener el mando de los datos de la aplicación, y aprender a “verdaderamente” instalarlo, es el primer paso!.

¡Happy Hacking!

[Bases de datos] ¿Es honesto sugerir tecnologías con obsolescencia programada?

Una de las cosas que se ha hecho más populares es sugerir el uso de discos de alta velocidad SATA SSD para labores de almacenar datos, metadatos y/o tablespaces dedicados para las bases de datos, pero, ¿es esto honesto?.

Por una parte utilizar SSD y sistemas de archivos sin journal de alto performance como XFS o EXT4 mejora de una manera notable el rendimiento de los sistemas de datos y esto se ha hecho una popular herramienta entre los DBA y administradores de sistemas y utilizarlos desde caché para optimizar el rendimiento hasta crear tablespaces sobre DRBD en RAID-over-Ethernet replicados, pero al igual que pasó con los discos duros Western Digital SATA-2 que venían con un interesante y fatídico “límite de parking-heads” (los discos venían con un límite máximo de parking de los cabezales de lectura, luego de sobrepasado ese límite, no se garantizaba la “salud” del disco, fallando el motor de encabezamiento del disco creando el famoso sonido del “WD Click of Death”); Intel ha liberado una serie de especificaciones (y luego de muchas quejas de usuarios que perdieron datos tanto en uso doméstico como en uso empresarial en bases de datos) que muestran el “uso y duración teórico de sus discos duros SSD”.

Lo que explican las especificaciones de sus modelos SSD es que, por mucho cuidado que le des a un disco SSD, este tenderá tarde o temprano (exactamente igual como le pasa a los pendrives USB) a perder su capacidad de retener datos y simplemente “freirse”.

¿Y de cuánto es ese límite?, en SSD de uso doméstico, esto puede ser un promedio de 5 a 16TB de datos escritos en disco, esto parecerá mucho tráfico para un disco, pero en condiciones normales se puede alcanzar ese límite en cuestión de 12 meses y a diferencia de un disco mecánico, que podrás desarmarlo y enviarlo a un centro de servicio especializado y “sacar los datos”, la pérdida de retención de los SSD significa (como alguien ha perdido su pendrive USB) la pérdida absoluta del medio.

¿Y qué pasa con los entornos empresariales que empezaron hace tiempo a utilizar SSD en sus bases de datos?, en condiciones de uso 24/7, reduciendo la capacidad máxima de escritura a 6 ó 10TB, aunque algunos modelos “modernos” de 600Gb aseguran tener una resistencia de entre 100TB y 500TB, estos límites de tráfico en una base de datos altamante activa se pueden conseguir en el término de 6 meses a un año.

Las preguntas alrededor de este problema son, ¿puede una empresa, en pos del “alto rendimiento” darse el lujo de comprar discos de > 1000US$ cada 6 meses porque se queman y hay que reemplazarlos?, ¿es seguro seguir armando notebooks, ultra-laptops y netbooks con discos SSD sin *avisarle* a la gente que un uso intensivo terminará acabando con el disco duro?, y si las empresas se acostumbran a “comprar y botar” discos duros; en algunos lugares dicen que es “perfectamente sano y normal” (¿normal?) reemplazar los discos duros SSD cada 6 ó 12 meses, ¿nuestra industria puede soportar tal generación de basura tecnológica?.

No todo es malo, al igual que el “error de Western Digital”, dudo que esto se mantenga por mucho tiempo, esta “carrera” por ofrecer velocidad a riesgo de “freir los discos” me imagino que generará una competencia por mejorar el diseño de los discos SSD o impulsará nuevas tecnologías (como el memristor entre otros) pero algo es cierto, es aún muy arriesgado suplantar discos duros por SSDs en los ambientes de almacenamiento de datos y aunque es cierto que el reemplazo de un disco duro por un SSD en un ultra-notebook o en un “all-in-one” causa una relación rendimiento-precio-mejoras contra los tradicionales discos duros (una familia regular o un usuario que sólo enciende su ultra-netbook para leer su correo en sus viajes y fuera de la oficina no quemarán su SSD durante mucho tiempo) el “no informar” de manera correcta a sus compradores sobre el uso y abuso del equipo, es cuando más, deshonesto.

¿cuántos de ustedes compraron esos discos SSD de almacenamiento externo de 1Gb de Samsung o Western Digital y terminaron al cabo de un año de uso intensivo con un hermoso ladrillo que se conecta por USB? …

Las 12 razones por las que un Administrador de Sistemas perezoso es un buen administrador

Hace muchísimo tiempo me enviaron este texto (lo encontré por acá) y es mi compendio de axiomas de trabajo en la administración de Sistemas, he decidido hacer una traducción libre de este artículo para que mis lectores disfruten un rato y comiencen a ser un poco más perezosos.

Si ves un administrador de sistemas, un técnico de soporte o un administrador de servidores, que siempre anda dando vueltas, como tratando de sofocar fuegos, que constantemente se ocupa de cuestiones relativas a detalles en la producción de sistemas y/o servidores; usted podría pensar que él está trabajando muy duro, ¡siempre tan dedicado!, esa es la concepción para la mayoría de las personas (de hecho, es una concepción de contratar esas personas “bomberos”), pero en realidad él no está haciendo bien su trabajo.

Si vemos a este administrador de sistemas (Unix/Linux, administrador de servidores, DBA o administrador de red) que parece estar todo el día “jugando”, que no parece estar haciendo mucho en la oficina, siempre relajado y casi nunca aparece ningún trabajo duro visible, puede estar seguro de que él está haciendo realmente bien su trabajo.

Estas son las 12 razones por las que un administrador de sistemas (sysadmin) perezoso, es el mejor administrador de sistemas.

Razón 1 ¿Quién es el jefe?: La razón principal por la que los Administradores de sistemas perezosos son los mejores es a causa de su actitud. Ellos ven las máquinas un poco diferente a la forma como las ven en otros departamentos de TI. Hay una diferencia notable entre los administradores de sistemas perezosos y otros admininistradores (ejemplo: los desarrolladores). Los desarrolladores piensan que están para servir a las máquinas mediante el desarrollo de código. No hay nada de malo en este enfoque, ya que los desarrolladores tienen mucha diversión allí; Sin embargo, los administradores de sistemas hacen todo lo contrario; ellos piensan que las máquinas están allí simplemente para servirles. Todo lo que tienes que hacer es alimentar la máquina y mantenerla feliz, dejando que la máquina haga todo el trabajo pesado, mientras pueda relajarse y simplemente dedicar su tiempo a ser perezoso. El primer paso para ser un administrador de sistemas perezoso es un ligero cambio en la actitud, y dejar que la máquina sepa que usted es quien manda.

Razón 2 Automatiza hasta el café: Ser un sysadmin perezoso no significa ser holgazán, debe esforzarse inicialmente para que todo fluya con soltura, debe escribir guiones de programación para trabajos repetitivos; en este aspecto ser perezoso es ser inteligente. Un administrador de sistemas inteligentes es un maestro en todos los lenguajes de scripting (bash, awk, sed, egrep, etc.) y cada vez que se vea obligado a hacer algún trabajo, y si hay una remota posibilidad de que ese mismo trabajo se repita en el futuro, entonces escribe un guión que repita este trabajo. De esta manera, en el futuro cuando se le pida hacer el mismo trabajo, no tiene que pensar, sino que simplemente tiene que ejecutar el script, y volver a ser perezoso.

Razón 3 evitar las pérdidas: Copia de seguridad de todo. Siendo sysadmins perezosos, siempre deben tener una copia de seguridad. Un administrador de sistemas perezoso sabe que debe realizar un poco de trabajo en la creación de procesos de copia de seguridad y escribir secuencias de comandos de copia de seguridad para todos los sistemas y aplicaciones críticas. Cuando el espacio en disco no es un problema, él programa la tarea de respaldo para cada aplicación, incluso para aquellas aplicaciones que no son críticos; de esta manera, cuando algo va mal, él no tiene ponerse a correr a recuperar cosas y sólo hay que restaurar desde la copia de seguridad, y volver a la lectura de comics que estaba haciendo antes.
Esta es también la regla #1 en las tres reglas del administrador de sistemas que JAMÁS se debe romper.

Razón 4 Crea un plan de recuperación ante desastres: A un Administrador de sistemas no le debería gustar correr cuando las cosas van mal (y ciertamente no debería habituarse a ello). Cuando las cosas están funcionando sin problemas, se debe tomar algo de tiempo para crear un DRP (Disaster-Recovery Plan); así, cuando las cosas vayan demasiado mal, pueden seguir el plan de recuperación rápida y que las cosas vuelvan a la normalidad, y volver a ser perezoso de nuevo!.

Razón 5 si no te puedes clonar, clona tus sistemas: La regla de los sistemas altamente redundantes. un sysadmin competente (y perezoso) no le gusta recibir llamadas en el medio de la noche a causa de algún problema de hardware que falló por una tontería; por ende, los sysadmins perezosos se aseguran que todos los componentes de su plataforma sean altamente redundantes. Esto incluye tanto hardware como software. Desde configurar tarjetas de red en modo bonding, RAID en discos, siempre al menos dos servidores o máquinas virtuales para cada cosa, siempre hay que tener al menos dos de todo. Por ende, cuando un componente falla, el sistema todavía sigue funcionando y el administrador del sistema perezoso puede dormir esa noche tranquilo y podrá trabajar en la reparación del componente roto mucho después de regresar temprano en la mañana.

Razón 6 Siempre debe haber espacio para crecer: Un sysadmin perezoso nunca permite que sus sistemas funcionen a plena capacidad. Siempre hay que disponer de espacio suficiente para el crecimiento inesperado; debe asegurarse que los sistemas tiene un montón de CPU, RAM y disco duro disponible; así, cuando su empresa decide volcar toneladas de información o genera inesperadamente muchos archivos, así no sufrirá insomnio pensando si la plataforma colapsará al quedarse sin recursos.

Razón 7 Sea proactivo: Ser un sysadmin perezoso no quiere decir que sólo se sientan y no hacen nada todo el tiempo. Siendo perezosos, se dedican a adelantarse a los hechos y ser proactivo. Los sysadmins perezosos odian ser reactivos. Se anticipan a los problemas y al crecimiento (razones 5 y 6). Cuando tienen algún tiempo libre, se dedican a investigar cómo evitar nuevos problemas, escribir nuevos scripts y modificar la plataforma para durante los problemas seguir siendo perezoso.

Razón 8 Ama tu teclado: combinaciones de teclado, un sysadmin perezoso conoce todos los atajos de teclado para todas sus aplicaciones favoritas. Si va a pasar mucho tiempo todos los días en una aplicación, lo primero que hace es dominar las comnbinaciones de teclas para esa aplicación. por eso los sysadmins perezosos aprenden a usar editores proactivos como emacs o vim, ya que a él le gusta gastar menos tiempo en la solicitud de la información a su máquina, para volver a ser perezoso.

Razón 9: Maestro de la línea de comandos: Cada sysadmin perezoso que conozco es un maestro de la línea de comandos. A veces la gente se sorprende de ver tanto tiempo al sysadmin en una “pantalla negra”; Esto no solo se aplica a sistemas Linux/BSD sino también a DBA’s, administradores de red, etc. Aunque exista una aplicación con interfaz gráfica para una tarea, usted verá al sysadmin lanzando una línea de comandos, En una interfaz de instalación de programas, por ejemplo, tendrás que cargar la aplicación, esperar que cargue, buscar el programa, darle a “seleccionar” y luego a “instalar”, en una cónsola escribes “migestor install miprograma” y listo, sabes exactamente que hacer en cada momento. Hay dos razones básicas por qué los sysadmins perezosos les encanta una línea de comandos. Por un lado, se pueden hacer las cosas más rápidamente en la línea de comandos (si se sabe hacerlo, claro está). Por otra parte, le hace sentir que él es el jefe y no la máquina. Cuando se utiliza la línea de comandos, usted está en control del sistema, usted sabe exactamente lo que quiere hacer y sabe lo que va a obtener. Cuando se utiliza una interfaz gráfica de usuario, usted está a merced del flujo de trabajo gráfico y no tiene el control total.

Razón 10 Aprende de los errores: a un sysadmin perezoso no le gusta cometer el mismo error dos veces. Él odia trabajar en problemas inesperados; pero, cuando surge algún problema inesperado, trabaja en su corrección y piensa acerca de por qué ocurrió, y de inmediato pone las cosas necesarias en su lugar para que el mismo problema no vuelva a ocurrir. Trabajar sobre el mismo problema dos veces es un pecado para un sysadmin perezoso. A un sysadmin perezoso le gusta trabajar en el problema una sola vez, hacer las cosas para evitar el mismo error que ocurra en el futuro, y volver a ser perezoso.

Razón 11 Nunca quedarse atrás: Aprende nuevas tecnologías. No hay nada malo en aprender una nueva tecnología para conseguir un trabajo mejor o simplemente para mantenerse al día con el crecimiento de la tecnología. Pero, nuestro sysadmin perezoso no aprende las nuevas tecnologías por este motivo; en cambio, se entera de las nuevas tecnologías, porque a él le gusta estar en control de los sistemas todo el tiempo. Él sabe que él es el jefe (Razón 1). Así que, cuando una nueva tecnología aparece, este se toma el tiempo para estudiarla. Ahora tiene nuevas herramientas que le permiten mantener el sistema activo, mientras que él sigue siendo un perezoso. Se documenta y aprende una nueva tecnología solo para mantener su egoísta pereza.

Razón 12 Nunca confiar en la mente, Documente todo: No todos los sysadmins perezosos lo hacen; sólo los mejores administradores de sistemas perezosos hace esto. Nunca a un sysadmin perezoso le gusta que le molesten cuando está en la playa disfrutando de sus vacaciones. Entonces, ¿qué hace? documenta todo, deja bitácoras y resoluciones para todo, así que cuando él no está cerca, otro técnico de soporte puede hacer el trabajo de rutina y hacer avanzar las cosas simplemente leyendo la documentación sin molestar las vacaciones del sysadmin. Hay también otra razón más íntima para que el administrador del sistema perezoso documente todo, porque pueden olvidarse las cosas. Puesto que él es perezoso, quizás tiende a olvidar lo que hizo hace un mes. Dado que nunca le gusta pensar el mismo tema dos veces (Corolario de la Razón 10), se documenta todo y cuando tiene que hacer lo mismo en el futuro, pues busca en su documentación para comprender como se hace.

Ahora, usted considerará que ser un sysadmin perezoso no es cosa fácil, es muchísimo trabajo duro, si usted no es un administrador de sistemas, puede que ahora aprecie al administrador vago que ve sentado en su computadora viendo Facebook mientras todo funciona perfectamente, recuerde que no funciona así solo. Si usted es un administrador de sistemas y siempre está dando vueltas apagando fuegos como bombero, usted ya sabe lo que tiene que hacer para ser perezoso.

¡A trabajar hoy, para descansar mañana!

[Trac] Instalando SCM Trac en Debian Wheezy y derivados (Ubuntu, Mint, Canaima)

Preámbulo

Un amigo me solicitó la bitácora de instalación de Trac en Debian Wheezy, había tenido algunos detalles utilizando Trac y postgreSQL 9, por lo que decidí publicarla para que más personas pudieran aprovecharla, sin embargo, como el Wiki de GNU de Venezuela no está operativo (donde estaba la versión Squeeze) entonces publicaré toda la guía por acá.

Instalación de Trac

Trac funciona en el modo “instancia”, cada instancia requiere de su propia base de datos y de su propia carpeta (instancia), pero comparten un único punto en el servidor web, aunque Trac utiliza por defecto sqlite para la base de datos, utilizaremos postgreSQL.

La instalación se realiza en una distribución Debian-based pero puede ser realizada en cualquier distribución GNU/Linux que posea python-setuptools y el comando easy_install (o pip).

Instalación de dependencias

  • Instalar las dependencias en Debian Wheezy (o distribución compatible con aptitude | apt-get):
aptitude install apache2 python2.7-setuptools python-genshi python-pybabel python-psycopg2 python2.7-psycopg2 libapache2-mod-wsgi python-babel babel-1.4.0 postgresql-8.4 subversion git mercurial bzr

Nota: si utiliza postgresql-9.1 con Trac < 0.12.2 tendrá que realizar una correción en el código fuente de Trac para poder crear instancias en schemas de postgreSQL 9.

Nota: Si se instala babel posterior a la instalación de Trac, deberá reinstalar trac y actualizar sus instancias.

  • Opcionalmente, podemos actualizar setuptools (requiere conexión a Internet)
easy_install -U setuptools

Instalación de Trac

  • Vía apt-get:
    apt-get install trac trac-bzr trac-git trac-graphviz trac-mercurial trac-odtexport trac-wikiprint
  • ó via easy_install:
easy_install Babel==0.9.5 Genshi==0.6
easy_install Trac
  • También podemos descargar el fuente e instalarlo manualmente:
    wget -c http://ftp.edgewall.com/pub/trac/Trac-0.12.2.tar.gz
    tar xvf Trac-0.12.2.tar.gz
    cd Trac-0.12.2
    python ./setup.py install

Nota: si deseamos instalar (o descargar) la versión de pruebas ejecutamos:

  • Usando easy_install:
easy_install Trac==dev
  • Descargando:
    svn co http://svn.edgewall.org/repos/trac/trunk trac
    cd trac
    python ./setup.py install

Por ultimo, luego de instalado, verificamos que tenemos la última versión:

trac-admin --version

Luego de instalado Trac, procedemos a configurar una instancia.

Configuración de una instancia

Preparación de la DB de postgreSQL

Agregar las siguientes líneas al archivo pg_hba.conf:

archivo: /etc/postgresql/{version}/main/pg_hba.conf

local tracdb tracuser password
host tracdb tracuser 127.0.0.1/32 md5
host tracdb tracuser [subnet]/24 md5
#para poder iniciar sesion en red:
host all all [subnet]/24 md5

Donde [subnet] se reemplaza por la subnet de la red local; ejemplo:

local tracdb tracuser password
host tracdb tracuser 127.0.0.1/32 md5
host tracdb tracuser 192.168.1.0/24 md5
#para poder iniciar sesion en red:
host all all 192.168.1.0/24 md5

Y en postgresql.conf modificamos:

listen_addresses = '*'

Nota: solo necesario si el postgreSQL y el Trac estarán en diferentes equipos.

  • Iniciar una consola y ejecutar:
su postgres
  • E iniciar una consola de postgreSQL:
    >psql
  • En la consola de postgreSQL, crear la DB:
  • Para crear una DB en > 8.4 ejecutar:
    CREATE DATABASE tracdb
      WITH ENCODING='UTF8'
           TEMPLATE=template0
           LC_COLLATE='C'
           LC_CTYPE='C'
           CONNECTION LIMIT=-1;
  • para 8.3 o inferior:
    CREATE DATABASE tracdb 
    WITH ENCODING='UTF8' 
    TEMPLATE=template0 
    LC_COLLATE 'C' 
    LC_CTYPE 'C';
  • Crear el usuario necesario para gestionar la DB:
create user tracuser password 'clavesecreta';
  • Y garantizar los permisos necesarios sobre la DB de trac:
    grant all on database tracdb to tracuser;
  • Salimos del postgresql:
postgres=# \q

Y reiniciamos el postgreSQL:

/etc/init.d/postgresql restart

Ya estamos listos para crear una instancia de Trac.

(Opcional) Preparación de Trac con postgreSQL 9.1

Nota: cambios iniciales para Trac 0.12 y postgreSQL 9.1

Si se intenta crear una instancia de Trac en postgreSQL 9.1 utilizando un schema personalizado (no “public”), Trac devolverá un error por un detalle en el uso de psycopg (la librería python para conectarse a Trac), dicho error se ve así:

Traceback (most recent call last):
  File "/usr/lib/python2.7/dist-packages/trac/admin/console.py", line 422, in do_initenv
    options=options)
  File "/usr/lib/python2.7/dist-packages/trac/env.py", line 213, in __init__
    self.create(options)
  File "/usr/lib/python2.7/dist-packages/trac/env.py", line 401, in create
    DatabaseManager(self).init_db()
  File "/usr/lib/python2.7/dist-packages/trac/db/api.py", line 146, in init_db
    connector.init_db(**args)
  File "/usr/lib/python2.7/dist-packages/trac/db/postgres_backend.py", line 98, in init_db
    params)
  File "/usr/lib/python2.7/dist-packages/trac/db/postgres_backend.py", line 87, in get_connection
    params)
  File "/usr/lib/python2.7/dist-packages/trac/db/postgres_backend.py", line 212, in __init__
    cnx.cursor().execute('SET search_path TO %s', (self.schema,))
DataError: invalid value for parameter "search_path": "weyu"
DETAIL:  schema "weyu" does not exist

Es un error en el archivo /usr/lib/python2.7/dist-packages/trac/db/postgres_backend.py, dicho error ya está corregido en versiones posteriores de Trac y existe un patch para dicho archivo:

  • Parche que está en la incidencia #10406 de Trac:

 http://trac.edgewall.org/attachment/ticket/10406/10406-search-path-r10830.patch

Si desean hacer los cambios ustedes mismos, las líneas a cambiar son:

Línea 34:

34	 	    from psycopg2 import ProgrammingError as PGSchemaError <- eliminar esta
 	34	    from psycopg2 import DataError, ProgrammingError <- agregar esta

Línea 214:

214	 	        except PGSchemaError: <- eliminar esta
 	214	        except (DataError, ProgrammingError): <- agregar esta

Con esta correción podrán crear instancias en postgreSQL 9.1.

Creando un ambiente base (environment Trac)

  • Creamos el árbol de proyectos:
mkdir /srv/{repositorios,trac,proyectos} -p
  • Nos dirigimos a la carpeta de proyectos:
cd /srv/proyectos
  • Inicializamos la primera instancia de trac (se llamará documentacion)
trac-admin /srv/proyectos/documentacion initenv
  • Se inicia un script que realliza una serie de preguntas:
Project Name [My Project]> Documentacion GNU/Linux
  • Conexión a la DB:
Database connection string [sqlite:db/trac.db]>
  • forma del database connection string
    ''{database}://{usuario}:{contraseña}@{host}:{port}/{database}?schema={schema}''

Ejemplo:

postgres://tracuser:clavesecreta@localhost:5432/tracdb?schema=documentacion

Nota: de usar el schema “public”, simplemente no pasar la opcion schema: ejemplo:

postgres://tracuser:clavesecreta@localhost/tracdb
  • Si deseamos usar unix-sockets:

postgres://user:pass@/dbname?host=/path/to/unix/socket/dir&schema=schemaname

Ejemplo:

postgres://tracuser:clavesecreta@/tracdb?host=/var/run/postgresql/.s.PGSQL.5432/dir&schema=documentacion

— Al terminar la configuración de trac, podemos iniciar las pruebas:

  • ejecutamos:

tracd –port 8000 /srv/proyectos/documentacion

Y apuntamos nuestro navegador a:

 http://host:8000/documentacion

Luego de chequeado, procedemos a configurar nuestra instancia de Trac.

Configuración de Apache y Trac

Debemos crear un ambiente web (www) con WSGI del Trac para apache, para ello desplegamos en la carpeta web (/srv/trac/www’) el sitio web:

trac-admin /srv/proyectos/weyu deploy /srv/trac/www/

Creamos el virtualHost para multiples proyectos de trac, creamos un archivo en:

/etc/apache2/sites-availables/trac.site

<VirtualHost *:80>
# administrador del servidor
ServerAdmin jesuslara@DOMINIO
# nombre del vhost
ServerName proyectos.DOMINIO
# alias del servidor
ServerAlias trac.DOMINIO
DocumentRoot /srv/trac/www/htdocs/

        <Directory />
                Options FollowSymLinks
                AllowOverride None
        </Directory>

WSGIScriptAlias / /srv/trac/www/cgi-bin/trac.wsgi

    <Directory /srv/trac/www>
        WSGIApplicationGroup %{GLOBAL}
        SetEnv trac.env_parent_dir /srv/proyectos
        Order deny,allow
        Allow from all
    </Directory>

    ErrorLog /srv/trac/www/log/apache-error.log
    CustomLog /srv/trac/www/log/access.log combined

</VirtualHost>
  • Creamos el directorio para los logs de apache:
mkdir /srv/trac/www/log && chown www-data.www-data /srv/trac/www/ -R
  • Modificamos el archivo trac.wsgi /srv/trac/www/cgi-bin/trac.wsgi:

Este queda:

#!/usr/bin/python
# -*- coding: utf-8 -*-

import sys
sys.stdout = sys.stderr

import os
import trac.db.postgres_backend
trac.db.postgres_backend.PostgreSQLConnection.poolable = False

os.environ['TRAC_ENV_PARENT_DIR'] = '/srv/proyectos/'

def application(environ, start_request):
    if not 'trac.env_parent_dir' in environ:
        environ.setdefault('trac.env_path', '/srv/proyectos/documentacion')
    if 'PYTHON_EGG_CACHE' in environ:
        os.environ['PYTHON_EGG_CACHE'] = environ['PYTHON_EGG_CACHE']
    elif 'trac.env_path' in environ:
        os.environ['PYTHON_EGG_CACHE'] = \
            os.path.join(environ['trac.env_path'], '.egg-cache')
    elif 'trac.env_parent_dir' in environ:
        os.environ['PYTHON_EGG_CACHE'] = \
            os.path.join(environ['trac.env_parent_dir'], '.egg-cache')
    from trac.web.main import dispatch_request
    return dispatch_request(environ, start_request)

Apache debe acceder al directorio de proyectos:

chown www-data.www-data /srv/proyectos -R
  • Y al directorio trac/htdocs:
chown www-data.www-data /srv/trac -R
  • Reiniciamos apache:
/etc/init.d/apache2 restart
  • Y ya podemos acceder a nuestra instancia vía la ruta del  virtualhost:

 http://host/documentacion

Quedando el directorio así:

.
|-- proyectos
|   `-- documentacion
|       |-- attachments
|       |-- conf
|       |-- htdocs
|       |-- log
|       |-- plugins
|       `-- templates
|-- repositorio
|   `-- documentacion
`-- trac
    `-- www
        |-- cgi-bin
        |-- htdocs
        |   |-- common
        |   |   |-- css
        |   |   |-- guide
        |   |   `-- js
        |   `-- site
        `-- log

(opcional) Configuración de múltiples ambientes (instancias)

Aunque se puede crear una base de datos para cada instancia, utilizaremos una única base de datos postgreSQL y schemas por cada instancia de Trac.

  • Inicializamos una nueva instancia:
trac-admin /srv/proyectos/lyx-book/ initenv
  • Configuramos la instancia:
Project Name [My Project]> Lyx Book

Database connection string [sqlite:db/trac.db]> postgres://tracuser:clavesecreta@localhost:5432/tracdb?schema=lyx
  • Propietario www-data a la carpeta del proyecto:
chown www-data.www-data /srv/proyectos -R
  • reiniciamos apache:
/etc/init.d/apache2 restart
  • Y ya podemos ver la nueva instancia en la lista de instancias:
  • al acceder al vhost, veremos la lista de instancias:

 http://host/

— Lista de instancias:

—————————————-

Available Projects

—————————————-

Autenticación inicial del Trac

La autenticación inicial se realizará vía htpasswd (en próximo artículo, agregaré la autenticación openldap).

  • Agregamos un usuario de sistema, para administrar el trac
useradd administrador
  • Creamos el archivo inicial para autenticar los usuarios con Trac
htpasswd -c /srv/trac/www/.htpasswd administrador
  • nota: inicialmente autenticamos con el usuario administrador, con la contraseña que le asignemos.
  • Y agregamos la entrada de autenticación al vhost del trac:
        <Location />
                AuthType Basic
                AuthName "Trac"
                AuthUserFile /srv/trac/www/.htpasswd
                Require valid-user
        </Location>
  • Luego, agregamos la info de autenticación via HTPASSWD al archivo de configuración de la instancia:
  • nota: el archivo de configuración de la instancia está en /srv/proyectos/{instancia}/conf/trac.ini, ejemplo:

archivo: /srv/proyectos/documentacion/conf/trac.ini

  • Agregamos la autenticación vía htpasswd:
[account-manager]
account_changes_notify_addresses =
password_file = /srv/trac/www/.htpasswd
password_format = htpasswd
password_store = HtPasswdStore
  • Le damos privilegios de TRAC_ADMIN al usuario administrador:
trac-admin /srv/proyectos/documentacion
  • Aparece la consola de la instancia de Trac:
-
Welcome to trac-admin 0.12.2
Interactive Trac administration console.
Copyright (C) 2003-2011 Edgewall Software

Type:  '?' or 'help' for help on commands.

Trac [/srv/proyectos/documentacion]>
  • Y en la consola ejecutamos el siguiente comando:
permission add administrador TRAC_ADMIN
  • Salimos de la consola:
>exit
  • Ejecutamos el upgrade de la instancia:
trac-admin /srv/proyectos/weyu upgrade
  • Y reiniciamos apache:
/etc/init.d/apache2 restart

Y ya podemos entrar al trac como el usuario administrador:

 http://host/documentacion/admin/

Ahora podemos personalizar ciertas opciones como incorporar plugins o agregar temas.

Incorporar un Tema a Trac

Para incorporar un tema a Trac, se debe primeramente incorporar el  http://trac-hacks.org/wiki/ThemeEnginePlugin Theme Engine Plugin

Instalación del Theme Engine Plugin

  • Descargamos el gestor de temas:
svn co http://trac-hacks.org/svn/themeengineplugin/0.11/ theme-engine
  • compilamos e instalamos:
cd theme-engine
python setup.py install
  • Habilitamos el theme engine plugin en el archivo conf/trac.ini
[components]
themeengine.* = enabled
  • Y reiniciamos el apache:
    /etc/init.d/apache2 restart

Ya podemos instalar un nuevo tema.

Instalar un Tema

  • Descargamos el tema que necesitamos:
svn co http://trac-hacks.org/svn/pydotorgtheme/0.11/ pydotorgtheme
  • Habilitamos el tema como plugin en el archivo conf/trac.ini
  • Se agregan a la sección ![components] del archivo trac.ini:
    pydotorgtheme.* = enabled
  • Habilitamos el tema en la sección ![theme] del archivo conf/trac.ini
[theme]
theme = PyDotOrg
  • Reiniciamos apache:
/etc/init.d/apache2 restart

Y ya contamos con un nuevo tema instalado.

Instalando un plugin de Trac

Para instalar un plugin de trac por la vía de la descarga, primero, ubicamos y descargamos la fuente;

  • Descargamos, el plugin de Mercurial
svn co http://svn.edgewall.com/repos/trac/plugins/0.12/mercurial-plugin
  • Nos movemos a la carpeta:
    cd mercurial-plugin
  • Ejecutamos la instalación del plugin:
python setup.py install
  • Y luego incorporamos dicho plugin al ‘conf/trac.ini’
[components]
tracext.hg.backend.*
  • Nota: podremos saber el nombre del componente a agregar en el archivo “setup.py > packages”.

Algunos plugins solicitarán actualizar (upgrade) de la instancia, para ello:

  • Ejecutamos en una cónsola:
trac-admin /srv/proyectos/documentacion upgrade
  • Y reiniciamos apache:
    /etc/init.d/apache2 restart

Configuración de repositorios

La configuración de repositorios (directorios donde se almacena código fuente versionado gracias a un VCS) depende de cada software de VCS utilizado, por defecto Trac gestiona Subversion, pero puede habilitarse para otros VCS.

Subversion

  • Instalamos subversion
aptitude install subversion libapache2-svn
  • Creamos la carpeta para el proyecto que deseamos versionar:
mkdir /srv/repositorio/proyecto-svn
  • Creamos el ambiente del proyecto SVN:
svnadmin create /srv/repositorio/proyecto-svn
  • Y le damos privilegio a apache para leerlo:
chown www-data.www-data /srv/repositorio -R
  • Entramos en el environment del trac:
trac-admin /srv/proyectos/documentacion
  • Agregamos el repositorio:
repository add proyecto-svn /srv/repositorio/proyecto-svn svn
  • nota: la sintaxis es: repository add {nombre} {ruta} {tipo}
  • Y ejecutamos la sincronización:
Trac> repository resync proyecto-svn 

Resyncing repository history for proyecto-svn ... 
0 revisions cached. 
Done.
  • Podemos ejecutar la resincronización de todos los repositorios existentes ejecutando:
repository resync '*'

Mercurial (Hg)

  • Instalamos el soporte a mercurial en nuestra distribución:
aptitude install mercurial
  • Descargamos el plugin
svn co http://svn.edgewall.com/repos/trac/plugins/0.12/mercurial-plugin
  • E instalamos el plugin de mercurial:
    cd mercurial-plugin
    python setup.py install
  • Configuramos el plugin de mercurial (hg) en el trac.ini
[components]
tracext.hg.backend.*
  • agregamos la configuración del plugin mercurial
    [hg]
    # -- Show revision number in addition to the changeset hash (defaults to yes)
    show_rev = yes
    # -- Changeset hash format
    node_format = short
  • Reiniciamos el environment de trac y apache:
trac-admin /srv/proyectos/documentacion upgrade && /etc/init.d/apache2 restart

Y ya tenemos configurado el soporte para Mercurial en Trac, ahora procedemos a agregar un repositorio:

  • Para agregar un repositorio Hg (Mercurial) creamos:
mkdir /srv/repositorio/hg/gnu
  • Nos movemos al directorio:
cd /srv/repositorio/hg/gnu/
  • Iniciamos Mercurial en la carpeta
    hg init
  • Y actualizamos:
    hg update
    0 files updated, 0 files merged, 0 files removed, 0 files unresolved
  • Entramos en el environment del trac:
trac-admin /srv/proyectos/documentacion
  • Agregamos el repositorio:
>repository add gnu-hg /srv/repositorio/hg/gnu hg
  • Y ejecutamos la re-sincronización:
    Trac [/srv/proyectos/documentacion]> repository resync gnu-hg
    Resyncing repository history for gnu... 
    0 revisions cached.
    Done.

GIT

Configurando Git

  • Instalamos lo necesario para git:
    aptitude install git git-core git-daemon-run
  • instalamos el plugin de GIT
    easy_install http://github.com/hvr/trac-git-plugin/tarball/master
  • Reiniciamos apache:
    /etc/init.d/apache2 restart
  • Agregamos la sección GIT al trac.ini
    [git]
    cached_repository = false
    persistent_cache = false
    shortrev_len = 7
    wiki_shortrev_len = 7
    git_bin = /usr/bin/git
    trac_user_rlookup = true
    use_committer_id = false
    use_committer_time = false
  • Y habilitamos el plugin (trac.ini)
    [components]
    tracext.git.* = enabled
  • Tambien agregamos la posibilidad de tener GIT post-commit hooks:
    [components]
    tracopt.ticket.commit_updater.committicketreferencemacro = enabled
    tracopt.ticket.commit_updater.committicketupdater = enabled
  • Y cambiamos esto (en el trac.ini):
    repository_sync_per_request = (default)

    — por esto:

    repository_sync_per_request =

Ya configurado GIT, creamos un repositorio.

Creación de un repositorio GIT

  • Creamos la carpeta:
mkdir /srv/repositorios/lyx-book
  • La convertimos en un repositorio git vacio:
    git --bare init
  • Nota: el directorio debe ser de tipo “bare”, ya que Trac debe tener acceso a los archivos de control (HEAD y config) de GIT y no solo el directorio .git/
  • Incorporamos los archivos necesarios, ejecutamos su adhesión al GIT:
    git add .
  • Ejecutamos el primer commit del repositorio:
    git commit -a -m 'first commit'
  • Verificamos su estado:
    git status
    # On branch master
    nothing to commit (working directory clean)
  • Cargamos la consola de la instancia:
    trac-admin /srv/proyectos/documentacion
    
    Welcome to trac-admin 0.12.2
    Interactive Trac administration console.
    Copyright (C) 2003-2011 Edgewall Software
    
    Type:  '?' or 'help' for help on commands.
    
    Trac [/srv/proyectos/documentacion]>
  • Incorporamos el repositorio:
repository add lyx-book /srv/repositorio/lyx-book git
  • Ejecutamos la sincronización:
    repository resync lyx-book

Conclusiones

Trac es una excelente herramienta  de SCM (Source Code Management) ya que combina Wiki, Gestión de incidencias (ticket, bug-tracking), gestión de código VCS y se le pueden incorporar plugins de terceros que incluyen desde un foro hasta un blog.

Detexify: El clasificador de símbolos de Latex

Para quienes trabajan con Latex (o Lyx que es su editor por defecto en GNU/Linux), se habrán dado cuenta lo tedioso que resulta insertar símbolos vía comandos latex y peor, lo engorroso que resulta saber “cual comando insertar”, existe una tabla, pero es extremadamente larga para ponerse a buscar.

Para ello, existe Detexify!

Detexify es un sitio web HTML5, donde la persona podrá “dibujar” el símbolo que quiere insertar y este tratará de reconocer por el trazo el símbolo al que se refiere, mostrando una lista de posibles “aproximaciones”; el sitio es realmente bueno, veamos un ejemplo:

He dibujado el símbolo de “copyleft” (a lo que el pulso me ha permitido) y este ha retornado el símbolo de copyleft y su comando (\textcopyleft) correspondiente.

Ha “adivinado” incluso mi horrible símbolo de libra!.

E incluso pudo descubrir que mi extraño símbolo se trataba de una corchea musical.

Evolución mundial de Navegadores web: viendo “más allá”

La gente de statscounter.org, uno de los sitios estándares para medir estadísticas de uso de sitios web, con más de 400 millones de sitios web registrados/analizados en todo el mundo y capturando las estadísticas de visita de millones de usuarios a nivel mundial, publicó el pasado 9 de Julio un video “bastante interesante” sobre la evolución de los navegadores web a nivel mundial, desde el año 2008 hasta el 2012.

El video, acá:

El video muestra las interacciones de los navegadores en todos los países desde 2008 hasta el 24 de junio de 2012 (día donde un navegador por fin le quitó la cima a Internet Explorer luego de 10 años -a nivel mundial-).

Como verán, Internet Explorer de Microsoft subsiste mayoritario exclusivamente en norteamérica, China y Australia, de resto, la mayoría de los países se han decantado por Firefox, Google Chrome y algunos (como Bielorrusia) por Opera.

Sin embargo, hay cosas que las imágenes cuentan mejor que las palabras y se prestan a más análisis detallados; por ejemplo:

En la semana 49 de 2009 (minuto: 1:05), se ve una clara tendencia a la disminución del uso de Internet Explorer en países latinoaméricanos como Brasil, Chile, Argentina y de manera superior Paraguay, Honduras y Ecuador, esto coíncide con la salida de la estable de Firefox 3.5 y el año de existencia de Google Chrome (que surgió en diciembre del 2008).

Google Chrome tenía para la fecha el 10% del mercado de navegadores en Paraguay y Firefox el 40% del mercado chileno; mientras, en Venezuela Firefox ocupaba el 25% y Chrome menos del 7% (aún cuando acá se “supone” que un decreto 3390 y una “comunidad de software libre muy activa” siempre están haciendo publicidad -mea culpa-).

Estadística interesante ocurre en la semana 18 2010:

En marzo de 2010, Paraguay “voltea” permanentemente sus preferencias de navegadores, posicionando Firefox “por encima” del resto de los navegadores, con además Google Chrome en un 15%, sólo países como México, Perú, Colombia, Bolivia o Venezuela mantienen su posición de utilizar preferentemente Internet Explorer.

En un período entre la semana 20 y la semana 32 de 2011 (salen Firefox 4, 5 y el “boom” de los Firefox y Google Chrome 12, todos con soporte webGL, HTML5 y otras ventajas), muchos países de latinoamérica “se voltean”:

Paraguay sigue su ruta de usar Firefox así como Honduras, se incorporan rápidamente Colombia, Ecuador, Chile, Argentina y Uruguay; no es sino hasta Septiembre del 2011 (unos 6 meses después que el resto de países) que Google Chrome pasa a ser líder de navegadores en Venezuela con 35% (no sería sino hasta Abril de 2012 que Firefox haría lo mismo), relegando a 22% el uso de “cualquier” versión de Internet Explorer en Venezuela:

¿Por qué empresas cómo la propia operadora estatal CANTV mantiene sitios web “sólo compatible Internet Explorer” así como el Tribunal Supremo de Justicia y otros entes?, en fin, no es de mi incumbencia, pero creo, que para los interesados, analizar el por qué y las razones de que un país como Venezuela (supuestamente y auto-proclamado “adelantado tecnológicamente” a sus vecinos) siempre le cuestan estas cosas del progreso tecnológico y de Internet; podemos hacernos algunas preguntas:

¿Cómo un país sin mar, que debe pagar convenios multilaterales con países como Bolivia, Perú o Argentina, para el paso de sus enlaces de fibra óptica con salida al mar, puede ofrecer anchos de banda de 2MB a 5MB dedicados a sus clientes desde el año 2008?, considero que el ancho de banda, el acceso a Internet por múltiples vías y ofertas baratas, son los que permiten a la gente descargar las aplicaciones que necesitan (en este caso navegadores web, pero pueden contarse ISO para masificar el uso de Linux) sin tener que esperar 15 minutos para bajar la última versión de Google Chrome (que es lo que tarda en casa de mi madre con ABA, en mi casa, con Internet móvil, tarda una hora).

También cabe preguntarse cómo en países como Paraguay ú Honduras, no se dejan llevar por “consumismos” y mientras acá el “teléfono” (si puede llamare así) más popular es el Blackberry (con 35% del mercado de Internet), en Paraguay Android, Symbian e iOS dominan el mercado, Android e iOS son los sistemas más utilizados en toda latinoamérica (las estadísticas se repiten en  todos lados), salvo acá, ¿tendrá que ver el hecho de la limitada oferta de equipos y la salvaje promoción del consumismo “embellecedor y efectista” versus la creación de consumidores responsables que saben qué comprar?; mientras países como Argentina (con el 60% de usuarios Android y sólo 3% de Blackberry) o Ecuador (con Android en 35% e iOS en 25%) “comparten” las estadísticas mundiales, acá sómos un país atípico, dónde las operadoras venden una cantidad “límitada” de equipos y donde extrañamente el Blackberry lo puedes comprar hasta en los buhoneros y quincallas-chollos ambulantes.

¿No se ve “solita” Venezuela allí? xD

Tome como nota interesante, que ni siquiera Canadá (país nativo de RIM, fabricante de Blackberry) tiene una estadísticas “tan alta” de uso de dicho dispositivo, de hecho, en las estadísticas de fabricantes de teléfonos, sólo Venezuela, La Guyana y República Dominicana son los únicos que no comparten la estadística mundial (Apple, Samsung, Nokia).

Más importante es, sin embargo, entender cómo las estadísticas contrastan con “lo que se dice”, mientras la tendencia latinoamericana es a “eliminar Windows XP”, acá sigue dominando con el 42% de las computadoras  (sólo Bolivia Y Cuba comparten con nosotros tan fatídica estadística), ¿no habría que considerar factores cómo su utilización como “estandar de facto” en la APN?, prometí no hablar de política, así que lo dejo a criterio del lector.

Creo que estas estadísticas, deberían a poner a pensar a más de uno, no importa legislaciones, decretos, leyes, reuniones, organizaciones, promociones, eventos, etc; si la gente no puede, por ejemplo, descargar una ISO para instalar un S.O o no puede acceder a algún contenido educativo, ¿cómo un país que debe pagar por su acceso a Internet como Paraguay puede brindar mejores y más baratos servicios que nosotros?, ¿cómo países tan pobres como Bolívia pueden tener mejores estadísticas que nosotros?, pero esta me gusta más, ¿cómo el 48% de los teléfonos en Cuba son Apple iPhone? … WTF!

[postgreSQL] Trabajando con fechas y generate_series

Un amigo me preguntó ¿cómo se hace en postgreSQL para obtener todos los días específicos de un mes?, ejemplo, “todos los días del primero al último en secuencia” o “el último día específico”, o “¿cuándo cae el black-friday en amazon este año?” o cosas como “¿cuántos lunes tuvo este mes?, debido a que llevaba mucho tiempo sin trabajar con postgreSQL, la pregunta me llevó por refrescar un poco …

Ahí recordé generate_series!

Una de las virtudes de “generate_series” es que nos permite obtener un conjunto consecutivo de valores enteros desde un valor “A”, a un valor “B” de manera muy sencilla:

SELECT generate_series(0,5)

Salida:

0
1
2
3
4
5

Esto, inicialmente no tiene mucho sentido asociado a trabajar con fechas, pero cuando te das cuenta que puedes operarlas vía intervalos y colocarlas en una consulta en el FROM, encontrarás cosas muy útiles cómo:

SQL: Obteniendo las fechas de cada día del mes en postgreSQL:

SELECT d.date, EXTRACT('month' from d.date) FROM
(SELECT generate_series(0,30) + first_day_month('2012-02-21'::date)::date as date) d
WHERE EXTRACT('month' from d.date) = EXTRACT('month' from first_day_month('2012-02-21'::date))

Nota: first_day_month es una función propia que retorna el primer día de un mes específico, lo pueden obtener con:

SELECT DATE_TRUNC('month', '2012-02-21'::date)

Como ven, la consulta genera un vector en el FROM, de una serie generada de sumar desde 0 al 30 a cada fecha desde la primera fecha del mes, si a ese vector le aplicamos un “WHERE” donde sólo me muestre los días que su MES coincida con el mes del primer día, tienes la función correcta que te retorna todas las fechas de un mes específico.

¿Cuántos lunes tiene el mes?

Para saber, vía “generate_series” las fechas en que cayeron todos los lunes del mes específico sería un simple “WHERE” contra la consulta anterior:

SELECT d.date, EXTRACT('month' from d.date) FROM
(SELECT generate_series(0,30) + first_day_month('2012-02-21'::date)::date as date) d
WHERE EXTRACT('month' from d.date) = EXTRACT('month' from first_day_month('2012-02-21'::date))
AND EXTRACT('dow'from d.date) = '1'

Verificando que “dow” (DAY OF WEEK”) es igual a 1 (Lunes).

Contarlos, es simplemente reemplazar el campo por un COUNT (GROUP implícito):

SELECT count(d.date) as n_lunes FROM
(SELECT generate_series(0,30) + first_day_month('2012-07-21'::date)::date as date) d
WHERE EXTRACT('month' from d.date) = EXTRACT('month' from first_day_month('2012-07-21'::date))
AND EXTRACT('dow'from d.date) = '1'

Y Julio tiene 5 lunes …

Computando fechas específicas

El Black-Friday (día interesante para los geeks que aprovechamos comprar cosas en Amazon xD) es una interesante fecha para calcular, es el día siguiente al “Día de Acción de Gracias” que son el cuarto jueves de Noviembre (el “black-friday” sería el 4 viernes de noviembre):

SELECT d.date FROM
(SELECT generate_series(0,30) + first_day_month('2012-11-21'::date)::date as date) d
WHERE EXTRACT('month' from d.date) = EXTRACT('month' from first_day_month('2012-11-21'::date))
AND EXTRACT('dow'from d.date) = '5' AND ((EXTRACT('day' from d.date)::integer+1)/7) = 3

Resultando que el “Black-friday” caerá el “2012-11-23”.

Claro, que simplemente podrías enumerar las semanas usando una función “ventana” (window functions) >

SELECT ROW_NUMBER() OVER (ORDER BY d.date) as position, d.date FROM
(SELECT generate_series(0,30) + first_day_month('2012-11-21'::date)::date as date) d
WHERE EXTRACT('month' from d.date) = EXTRACT('month' from first_day_month('2012-11-21'::date))
AND EXTRACT('dow'from d.date) = '5'

Y esto retorna:

1   |   “2012-11-02”
2   |  “2012-11-09”
3   |  “2012-11-16”
4   |  “2012-11-23”
5   |  “2012-11-30”

Conclusiones

Uno de los grandes problemass a la hora de utilizar un RDBMS, es tratar de mantenerse “genérico”, sin pensar en utilizar funciones específicas del lenguaje que podrían optimizar nuestro trabajo al máximo, de hecho, en Oracle la mayoría de los ejemplos acá presentes se hacen con PL/SQL o con cláusulas WITH más complejas que nuestra corta función SQL usando “generate_series”.

A %d blogueros les gusta esto: