martes, 23 de octubre de 2007

Update condicional

¿Cómo se hace un UPDATE condicional?
Digamos que tengo una tabla t con 3 campos a, b y c. Quiero que si a=1 entonces actualizo b con algún valor, y si a=2 actualizo c.

Alguien de mi equipo se encontró con este dilema y lo resolvió de forma muy práctica: dos updates, uno para actualizar aquellos valores con a=1 y otro para actualizar los a=2:

1 BEGIN
2    UPDATE t
3   SET b=valor
4   WHERE a=1;
5

6   UPDATE t
7   SET c=valor
8   WHERE a=2;
9 END;

Otro programador del equipo refutó: -¿Para qué ejecutar dos sentencias update si en su lugar puedes hacer una?

1 BEGIN
2   UPDATE t
3   SET B=DECODE(A,1,valor,2,B),
4   C=DECODE(A,1,C,2,valor);
5 END;


¿Quién de los dos tiene razón?

...depende.

Dado que la performance parece ser lo que está en juego, la primera pregunta que cabe es:

¿Tiene la tabla t índice por A?

Si la tabla no tiene índice, entonces debemos recorrerla por entero. En el primer caso recorremos la tabla dos veces, mientras que en el segundo caso lo hacemos solamente una! Por lo tanto la primera solución en este escenario es el doble más lenta que la segunda. Al notar que la tabla no tiene índices, el Programador 2 asiente la cabeza con orgullo.

Inmediatamente el Programador 1 reacciona: -Pongámosle un índice a t entonces!
(el ávido Programador 1 sabe que la segunda consulta no puede sacar provecho de un índice por lo que su victoria parece asegurada)

Y aquí es donde cabe la segunda pregunta:

¿Cuál es la cardinalidad de la columna A?

Sería de gran ayuda saber si 1 y 2 son la mayoría de los valores que hay en la columna A, porque en ese caso, el optimizador va a continuar prefiriendo recorrer toda la tabla! Si la cardinalidad de los valores 1 y 2 son un porcentaje muy bajo del conjunto de valores distintos, entonces recién ahí los índices van a ser utilizados.
Cuando el índice es utilizado por la escasa presencia de valores 1 y 2, los tiempos de la primer solución es abismalmente inferior.

Conclusión:

La solución 1 es mejor si existen índice sobre la columna A y su cardinalidad es alta (hay pocos 1 y 2 en A).
La solución 2 es mejor si no existen índices o existe y la cardinalidad de A es baja para valores 1 y 2 (significa que 1 y 2 ocurren mucho en A).

Ver también:
Mis índices no funcionan!
Indices condicionales