www.jjcosta.com

Principal
Ruby - Python
Gico
Camino de Santiago
Interbase

Optimización Interbase

Recomendaciones obtenidas de los siguientes artículos:
Optimization I: Optimizing InterBase Applications
Optimization II: Optimizing InterBase SQL and Metadata
Optimization III: Selecting and Configuring InterBase Server Hardware


Reducir el número de registros a revisar y a obtener:

   Evitar el uso de select (*), es mejor hacer Select campo1, campo2, ...
   Utilizar clausula Where para reducir el número de registro a obtener
   Para tablas pequeñas y fijas cachearlas en el cliente
   Evitar el uso de inner join (2*), siempre que sea posible
   Evitar el uso lookup en Delphi, es preferible hacer sql joins
   Evitar hacer subconsultas correlativas, es mejor hacer joins (mejora el plan de la consulta), ver ej.

Evitar el uso de Select Count (*):

   Determinar si una tabla está vacía en código:
      if not MyTable.IsEmpty then begin
         DoSomething;
      end else begin
         raise Exception.Create(NORECORDS);
      end;

   Determinar si una tabla está vacía en Sql o procedimiento o trigger
      RDB$DATABASE es una tabla del sistema que siempre tiene un registro
      SELECT 'Table is not empty' FROM RDB$DATABASE
         WHERE EXISTS (SELECT 1 FROM SOME_TABLE);

Evitar hacer iteraciones en el cliente:

   En el caso de tenerlas que hacerlas:
      while not MyTable.Eof do begin
         DoSomething;
         MyTable.Next;
      end;

   Copiar varias filas de una tabla a otra:
      INSERT INTO DESTINATION_TABLE (DEST_ID, SOURCE_ID, DESCRIPTION )
      SELECT GEN_ID(DEST_G, 1), SOURCE_ID, DESCRIPTION
      FROM SOURCE WHERE

   Para borrar Muchas filas a la vez:
      DELETE FROM TABLE WHERE SOME_DATE BETWEEN :StartDate AND :StopDate
   Para realizar cálculos utilizar select max, min, avg, sum o funciones udf,
      y cuando no sea posible hacer los cálculos en procedimientos almacenados
   Evitar hacer procedimientos almacenados, cuyo tiempo de ejecución sea excesivamente largo,
      puede ir en decremento de los demás clientes

Uso de commit y rollback:

   Es preferible hacer commit y rollback que commit_retaining y rollback_retaining (no terminan la transacción)
   Evitar el uso de Rollback

Uso de índices:

   Comprobar el uso correcto de los índices
   Son útiles cuando se quiere leer pocas filas de datos
   Es mejor indexar sobre columnas unique, y no hacer dos veces sobre la misma columna
   Hacer índices sobre campos que seán selectivos
   En la cláusula where las n primeras columnas deben ser las n primeras columnas del índice a usar
       (todas, o las n primeras) en el mismo orden
   Crear un índice por cada columna del "where", o sólo uno que se muy selectivo
   Índice descendiente -> función Max
   Índice ascendiente -> función Min, Select desc from tabla where cod = 100 ;
   Para funciones Sum, Avg no se puede aprovechar los índices
   Rebalancear índices con alter index xx inactive / active (cuidado con clientes activos)
   Interbase's optimizer tratará de evitar un índice que no sea sumamente selectivo,
      pero no podrá crear un índice donde no exista.

Evitar el uso de índices:

   Select emp_no, first_name, last_name || '' from Employee order by 3, 2(Para nímeros 0 ||)
   No son útiles cuando se tienen que leer todos o casi todos los datos,
      o no reducen en consideración el número de registros a leer,
      es decir el índice es poco selectivo,
      sobre todo si el orden del índice no coincide con el orden de almacenamiento.
   Un gran número de índices penaliza las inserciones (por tener que ir actualizando
      todos los índices por cada inserción)
   Ver apartado ordenando los datos

Ordenando los datos:

   La manera más rápida de obtener los registros es en el orden de almacenamiento
      donde el plan sea (PLAN (NOMBRE_TABLA NATURAL)
   Hay dos formas de ordenador un resultado, leyendo los datos en orden usando un
      índice o leer todos los datos en el orden que están almacenados y después
      hacer la ordenación en memoria. Para un gran volumen de registros suele más
      rápido las segunda opción, sin embargo, la pérdida de velocidad de la primera
      opción, se puede compensar si reduce apreciablemente el número de registros
      a leer al usar el índice. (nota: el movimiento del disco duro (no secuencial),
      buscando los registros en orden, es más lento respecto a una lectura secuencial
      y después realizar un QuickSort

Uso de like:

   Evitar el uso de "where nombre like '%t%'" no aprovecha el uso de índices,
      reemplazar si es posible por "where nombre like 't%'"
   Evitar el uso de "where nombre like :nombre"
      reemplazar por "where nombre starting with :nombre"

Uso de Union:

   Reemplazar el uso de Union (elimina duplicados) por Union all , cuando sea posible

Evitar consultas con subconsultas, que tengan comparaciones de columnas con mas de 1 cte.

   Select * From EMP_PROJECT Where EMP_NO In
      (Select EMP_NO From EMP Where NAME In ('Nelson', 'Young'));
   Select * From EMP_PROJECT Where EMP_NO In
      (Select EMP_NO From EMP Where (NAME = 'Nelson') OR (NAME = 'Young'))

   Solución:
   Crear una tabla con las ctes a buscar
      Select * From EMP_PROJECT Where EMP_NO In
         (SELECT EMP_NO FROM SELECTED_EMPLOYEES;)

   Utilizar Union or Union ALL
      Select * From EMP_PROJECT Where EMP_NO In
         (Select EMP_NO From EMP Where NAME = 'Nelson')
      UNION ALL
      Select * From EMP_PROJECT Where EMP_NO In
         (Select EMP_NO From EMP Where NAME = 'Young')