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.