Oracle 9 Sin Estadísticas

Si administrás una base de datos Oracle versión 9, calculá las estadísticas de todos los objetos y bastante seguido.

Cuando Oracle arma el plan de ejecución, si no tiene estadísticas para alguna tabla y sí tiene para otra, estima a grosso modo las que no están y el plan resultante es una basura que terminará leyendo muchísimos bloques innecesariamente.

En mi experiencia, un query que actuaba sobre una tabla de millones de registros pasó de 48 horas a 2 horas sólo por el cálculo de las estadísticas. Es especialmente importante cuando se hacen consultas que involucran joins.

Además, el cálculo de las estadísticas no interfiere con otras operaciones y puede ser programado para realizarse en los momentos en que no se está usando y se puede dividir por particiones y por esquema para distribuir el cálculo en el tiempo.

Usar índices con valores nulos

En Oracle, los valores nulos no se indexan. Esto hace que las consultas que usan “is null” o “is not null” como condición requieran un table full scan.

Para evitar eso una forma es poner un valor especial para representar el null. Por ejemplo cero.

Así se va a usar ese índice sin problema. El tema es que hay que asignar un valor para que represente el null.

Oracle no crea índices para las claves foráneas

Cuando se define una restricción de clave foránea en Oracle, el motor no crea un índice para la columna que se restringe. Eso significa que cualquier consulta sobre la tabla del estilo

select *
from detalle
where id_maestro = 10

no serán optimizadas. Es un regla en el 99% de los casos que ese índice será necesario.

En el ejemplo la clave foránea sería la que hace que la columna id_maestro de la tabla detalle es la clave primaria de otra tabla.

Optimización al leer de un ResultSet

Acabo de desasnarme respecto a una funcionalidad que está disponible en JDBC y que me parece muy prometedora.

Cuando se leen datos de la base se hace de a una cierta cantidad de filas por lectura. Si sabemos de antemano que vamos a leer todo el result set y tenemos memoria disponible, podemos aumentar esa cierta cantidad del valor por omisión (10) a algo más grande.

Esto reduce la cantidad de lecturas y hace que cada lectura sea más extensa.

Es muy sencillo, al crear el PreparedStatement le seteamos el fetch size:

procedure.setFetchSize(5000);

Malabarismo en Oracle

Tengo que copiar unos 30 millones de registros de una tabla en la que hay unos 200 millones a otra tabla y obtuve un error: no se puede agrandar el índice porque no hay espacio en el tablespace. La base es Oracle 9.2

Para solucionarlo tuve que mover todas las tablas e índices de ese tablespace a otros tablespaces que tuvieran lugar. Así liberé 3 GB.

Luego saqué de la tabla destino las columnas que no necesitaba así sólo traeré las realmente indispensables.

Espero que me alcance el lugar porque si no tendré que llamar al DBA.

Así se puede ver el espacio libre en cada tablespace

select tablespace_name, trunc(sum(bytes) / (1024 * 1024)) as “MB Libres”
from user_free_space
group by tablespace_name

Para mover todas las tablas de un tablespace a otro hice un script SQL que me generó las sentencias.

select ‘ALTER TABLE ‘|| table_name ||’ MOVE TABLESPACE TABLESPACE_LIBRE;’ as query
from user_tables
where tablespace_name = ‘TABLESPACE_LLENO’

Y lo mismo para los índices.

select ‘ALTER INDEX ‘|| index_name ||’ REBUILD TABLESPACE TABLESPACE_LIBRE;’ as query
from user_indexes
where tablespace_name = ‘TABLESPACE_LLENO’

Firebird 2.1 trae cosas nuevas

Parace que Firebird 2.1 va a incorporar un par de novedades interesantes.

  1. Global Temporary Tables (tablas temporales) que adhieren al estándar.
  2. Una función LIST para usar en los group by como tiene Sybase.
  3. Cancelación asincrónica de queries.

Cómo elegí Firebird (antes Interbase)

Justo para la época en la que estaba buscando una base de datos que fuera software libre y luego de descartar MySQL (3.23) por no tener implementado casi ninguno de los conceptos centrales de las bases de datos relacionales, Borland liberó el código fuente de Interbase 6.0.

Interbase era una base de datos bastante usada por venir integrada con Delphi en aplicaciones de escritorio sencillas, pero no por eso dejaba de ser una base de datos cliente servidor muy potente.

Lo que me compró fue el nivel de adherencia que tenía con el estándar SQL. Dominios, claves foráneas, triggers, stored procedures, subconsultas, vistas, transacciones al estilo SQL estándar (no al estilo transact-sql de sybase y MS SQLServer).

Lo segundo que me impactó mucho fue el hecho de ser una base de datos con control de concurrencia utilizando múltiples versiones de los datos. Así reducía la necesidad de lockear registros en ciertas operaciones y últimamente muchas bases de datos están implementando este mecanismo que Interbase tiene desde siempre.

Borland dejó de hacer libre el código de Interbase, por eso surgió el proyecto Firebird.

MySQL es peligroso

Sigo enterándome de las rarezas que hay en distintas versiones de MySQL.

La sentencia drop database es un chiste….

http://dev.mysql.com/doc/refman/5.0/en/drop-database.html

Borra una a una las tablas y si no puede borrarlas todas falla y deja algunas sin borrar, por lo que hay que ejecutarlo de nuevo hasta que borre todo. Si hay archivos en el directorio hay que borrarlos a mano…

El manejo de los valores por omisión es una pesadilla si se tiene en cuenta que se combina con que MySQL cambia los valores al insertar o actualizar si es que no se adpatan al tipo de la columna. Una aberración bajo cualquier punto de vista.

Cuando recién empecé a usar software libre en mi viejo Windows 98 por estar cansado de tener que crackear los programas para poder usarlos empecé a evaluar bases de datos y la que primero apareció en mi radar fue MySQL.

Yo tenía bastante noción de algunos conceptos como las propiedades ACID pero nunca había trabajado con ningnua base de datos seriamente. Mientras leía el manual de MySQL 3.23 me entusiasmaba con que usaba árboles B* para los índices y con los reportes que era muy rápida y liviana. En esa época yo tenía una Pentium con 64 MB de memoria.

Rápidamente detecté falencias insalvables:

  1. Permitía declarar las restricciones de clave foránea, pero no tenían ningún efecto.
  2. Se podían declarar transacciones pero no funcionaban.
  3. Aclaraban que si bien no implementaban las propiedades ACID, las operaciones se hacían en forma atómica. (¿?)

Por supuesto que llegué a instalar el motor InnoDB y a crear algunas tablas, pero me pareció que sería más fácil usar otra base que fuera más ortodoxa.

Lo más llamativo es que versión tras versión han ido implementando una a una las funcionalidades que la versión 3.23 no tenía (triggers, vistas, stored procedures, etc.) lo que me hace pensar que las versiones viejas no eran tan buenas como se decía.

Si realmente MySQL es la base de datos ideal para proyectos en los que una base de datos tradicional (es decir una base de datos) no hace falta, ¿por qué en cada nueva versión se parecen más a una?

MySQL ya casi es una base de datos

Me estoy informando del estado actual de la base MySQL. Están en la versión 5.1 y en ella aparece por primera vez la aritmética decimal exacta. Sí, en la versión 5.0.x y todas las anteriores sumar, multiplicar, restar y dividir valores de tipo DECIMAL o NUMERIC acarreaba errores de redondeo. Lo bueno es que ya está la versión 5.1 que permite hacer esos cálculos sin pasar los valores a coma flotante.

Pero no es del todo bueno porque dependen de que esté seleccionado el llamado modo estricto de lo contrario los overflows pasan inadvertidos y se guardan valores válidos a pensar de que el resultado de la operación no encaja en la precisión de la columna. Increíble.

Los genios de MySQL han logrado un avance histórico en la matemática: la división por cero da como resultado NULL. A menos que seleccionemos el modo ERROR_FOR_DIVISION_BY_ZERO.

Creo yo que MySQL 5.0 ya es casi una base de datos, si se la configura en modo estricto y si no se permite cambiar ese modo a nadie para esquivar las verificaciones. Eso es un tema, porque cualquiera puede cambiar el modo de su sesión en cualquier momento…

Si tenemos en cuenta que muchos todavía usan MySQL 3.23 o 4.x, y que aún con la versión 5.0.3 no obtienen la aritmética decimal exacta aunque la quieran, creo que el panorama es desalentador.

Aquí está la lista de modos soportados con su explicación.