3
Mar 14

Pildoritas de POO y Java: Conceptos básicos de programación. Operaciones

pildoras poo java
En la anterior pildorita de POO y Java vimos qué era un algoritmo y enumeramos los tipos de instrucciones que los componen y que nos permiten describir un problema: Datos, Operaciones y Sentencias. Además, vimos la primera parte, los Datos.

En esta pildorita vamos a ver el siguiente componente que forma un algoritmo: Las operaciones. Veremos los tipos de operadoresy su orden de precedencia.

Operaciones

Las operaciones son sentencias que realizan un cálculo sobre varios datos. Para realizar dichos cálculos tenemos una serie de operadores aritméticos (sumar, restar, multiplicar...), lógicos (mayor que, menor que, igual que...), y de asignación.

Los operadores sólo pueden ser utilizados con determinados tipos más o menos restrictivos (hay operadores que sirven para numéricos, otras para numéricos y de texto..). Además, los operadores pueden ser utilizados con dos datos – binarios - con un dato – unarios - e incluso terciarios.

Operadores aritméticos

Los operadores aritméticos actúan sobre datos numéricos, es decir, enteros y de coma flotante. Los básicos son + (sumar), - (restar), * (multiplicar), / (dividir) y % (módulo, que es el resto de una división de enteros).

Binarios

Operador Símbolo Descripción
Suma + Suma dos operandos
Resta - Resta dos operandos
Multiplicación * Multiplica dos operandos
División / Divide dos operandos
Módulo % Devuelve el resto de la división de dos operandos
//Suma
int resultadoSuma = 5 + 2; // resultadoSuma vale 7

//Resta
float resultadoResta = 5.3f - 2.07f; // resultadoResta vale 3.2300003

//Multiplicación
short resultadoMultip = 10 * 2; //resultadoMultip vale 20

// División
long resultadoDiv = 1238907 / 92384; //resultadoDiv vale 13

// Módulo		
int resultadoMod = 10 % 3; //resultadoMod vale 1

El operador suma, +, también puede operar con los String, concatenándolos entre ellos. También podemos concatenar a las cadenas valores de otros tipos, como int o long. Veamos un ejemplo:

System.out.println("resultadoSuma: " + resultadoSuma);

El comando System.out.println sirve para mostrar por consola un input introducido como parámetro (entre los paréntesis). Lo que veríamos por pantalla en este caso sería lo siguiente:

"resultadoSuma: 7"

Unarios

Operador Símbolo Descripción
Conversión de entero + Convierte el operando a entero si es un byte, short o char
Negación - Negación aritmética del operador (cambio de signo)
int a = -5;
int b = -a; //b vale 5

Operadores Lógicos

Los operadores lógicos comparan dos valores y devuelven la relación existente entre ambos. Por tanto, el resultado de estos operadores es de tipo booleano, es decir, en términos de verdadero o falso.

Los operadores lógicos a su vez pueden dividirse en dos subtipos: comparación y condicionales. Ambos tipos de operadores además se pueden combinar para realizar expresiones más complejas.

Operadores de comparación

Operador Símbolo Descripción
Mayor que > Devuelve true si el primer operando es mayor que el segundo
Mayor o igual que >= Devuelve true si el primer operando es mayor o igual que el segundo
Menor que < Devuelve true si el primer operando es menor que el segundo
Menor o igual que <= Devuelve true si el primer operando es menor o igual que el segundo
Igual == Devuelve true si los dos operandos son iguales
Distinto != Devuelve true si los dos operadores no son iguales
//Mayor que
boolean mayorQue = 3 > 1; //mayorQue vale true

// Menor que
boolean menorQue = 3 < 1; //menorQue vale false

//Mayor o igual que
boolean mayorIgualQue = 3 >= 3; //mayorIgualQue vale true

//Menor o igual que
boolean menorIgualQue = 3 <= 1; //menorIgualQue vale false

//Igual
boolean igual = 5 == 5; //igual vale true

// Distinto		
boolean distinto = 5 != 5; //distinto vale false

Operadores condicionales

Los operadores condicionales actúan sobre dos datos de tipo booleano, y devuelven un resultado también booleano. También pueden evaluar dos expresiones de comparación, ya que estas expresiones devolverán valores boolean.

Para mayor comprensión de los operadores condicionales os recomiendo ver el apartado de Operadores Condicionales de la Pildorita de Bases de Datos sobre Cláusulas. Las tablas de la verdad os pueden ayudar a comprenderlos mucho mejor

Operador Símbolo Descripción
AND && Devuelve true si ambos operadores son verdaderos
OR || Devuelve true si uno de los operadores es verdadero
Falso ! Opera sobre un elemento y devuelve su valor contrario
//AND
boolean and = true && true; // Vale true
boolean and2 = true && false; //Vale false
boolean andComplejo = (2 > 3) && (1 < 5); //false AND true: Vale false

//OR
boolean or = true || false; //Vale true. El intérprete ni siquiera mirará el sgundo elemento
boolean or2 = false || false; //Vale false
boolean orComplejo = (2 < 3) || (1 > 2); //Vale true

//Negacion
boolean not = !(3 > 1); //not vale false

Operadores de asignación

Los operadores de asignación son operadores especiales que asignan un valor a una variable. El operador básico ya lo hemos visto en anterior ejemplos, el =, pero en conjunción con otros símbolos como el de suma, se pueden realizar atajos.

Binarios

Operador Símbolo Ejemplo Expresión equivalente
Asignación básica = A = B; No Aplica
Suma += A += B; A = A + B
Resta -= A -= B; A = A – B
Multiplicación *= A *= B A = A * B
División /= A /= B A = A / B
Modulo %= A %= B A = A % B
//Asignación básica
int c = 5; // c vale 5

//Suma
c += 15; // c vale 20

//Resta
c-=5; //c vale 15

//Multiplicación
c *= 2; //c vale 30

//División
c /= 2; //c vale 15

//Módulo
c %= 10; //c vale 5

Unarios

Operador Símbolo Descripción
Post-incremento op++ Incrementa en 1 el operador. Se evalúa el valor anterior al incremento
Pre-incremento ++op Incrementa en 1 el operador. Se evalua el valor posterior al incremento
Post-decremento op-- Decrementa en 1 el operador. Se evalúa el valor anterior al incremento
Pre-decremento --op Decrementa en 1 el operador. Se evalúa el valor posterior al incremento
int unarios = 8;

unarios++; //unarios vale 9
++unarios; //unarios vale 10
unarios--; //unarios vale 9
--unarios; //unarios vale 8

boolean postfijo = (9 == unarios++); //postfijo vale false
boolean prefijo = (9 == unarios++); //prefijo vale true

Orden de precedencia

Cuando construimos expresiones complejas donde utilizamos más de un tipo de operador, hay que tener en cuenta el Orden de precedencia de los Operadores.

Operador Símbolo
1 operadores unarios postfijos op++, op--
2 Operadores unarios prefijos ++op, --op, +op, -op, !
3 Multiplicación y División *, /, %
4 Suma y Resta +, -
5 Operadores relacionales <, >, <=, >=
6 Operadores de equivalencia ==, ¡=
7 AND &&
8 OR ||
9 Condicional ?:
10 Operadores de asignación =, +=, -=, *=, /=, %=

 

Para romper el orden de precedencia, al igual que en las matemáticas, utilizaremos paréntesis o corchetes.
  
Y con esto terminamos esta pildorita de operaciones. En próximas pildoritas hablaremos de las sentencias de flujo de ejecución, las funciones y finalmente ciertas consideraciones especiales de Java.

Índice de Pildoritas

Share
23
Oct 13

Pildoritas de Bases de Datos: Optimización. Consideraciones de rendimiento de los operadores

pildoras bbdd

¡Sorpresa! Sí, tras tan sólo una semana de espera vuelven de nuevo las Pildoritas de Bases de Datos. La pildorita de hoy está dedicada a consideraciones de rendimiento de los operadores... OH, WAIT!

Si, dije que primero veríamos los WHERE SARGABLE, pero también que me estaba costando horrores organizarme las ideas y que no era definitivo (ya me imaginaba que esto podía ocurrir xD), así que sintiéndolo mucho, tendréis que esperar un poco más para salir de dudas con el tema del WHERE SARGABLE (culpa vuestra por no haberlo buscado ya 😀 )

Que conste que comencé con el tema de NON-SARGABLE primero, pero al ver que había temas que se me iban a mezclar con los operadores, no me quedó más remedio que darle la vuelta a la idea inicial y comenzar por éste tema.

Como decía (ya me empiezo a liar), en esta pildorita veremos cuestiones sobre el rendimiento de los operadores y posibles alternativas para evitar utilizar aquellos más costosos.

Tanto en esta pildorita como la siguiente hay que tener siempre claro que muchas de estas pautas no son más que simples consejos. La optimización es todo un mundo y muchas veces las pautas típicas de nada sirven y hasta es posible que lo contrario a lo que pensábamos sea la solución. En estos dos temas intentaré dejar siempre claro que esto no son reglas absolutas, pero me gustaría destacarlo para que así lo tengamos siempre presente.

Bueno, no me enrollo más, al lío xD

Rendimiento de operadores en el WHERE

Como decía hace un momento, el rendimiento de los operadores puede variar en cada consulta, pero se pueden clasificar de mejor a peor rendimiento de la siguiente forma:

  • =
  • >, >=, <, <=
  • LIKE
  • <>

A parte del operador en sí, también repercuten en el rendimiento otras cuestiones como el tipo de los operandos utilizados, el orden de estos, etc.

Ordenadas de mejor a peor rendimiento, estas son las otras pautas que también hay que tener en cuenta con respecto a los operadores:

  • Utilizar un literal único en lugar de varios
  • Utilizar un nombre de columna o un parámetro
  • Una expresión multiperando
  • Un número único exacto
  • Un número único no exacto al lado de un operador (date, time)
  • Datos de caracteres o NULL.

No obstante, esto pocas veces tiene mucha importancia ya que no es aplicable cuando el WHERE contiene más de una expresión, así que estos consejos rara vez podrán solucionaros la vida.

Operador IN

Siempre que podamos intentaremos sustituir este operador por cualquiera de las siguientes opciones.

EXISTS

NOT EXISTS, al estar conjugado con el operador NOT es NON-SARGABLE (por ahora sólo basta con saber que es malo xD), pero pese a ello su rendimiento es mejor que el IN muchas veces. Otras veces lo mejor es variar por IN utilizando el conjunto complementario de elementos, o en caso de que sea sólo un caso el comando EXISTS con esos complementarios, ya que es mucho más eficiente que el IN.

Vamos a verlo una vez más con un ejemplo. Imaginemos que queremos ver los datos de empleado de aquellos que no tengan proyecto.

SELECT NOMBRE, APELLIDOS, DNI, TELEFONO, ID_PUESTO, ID_COMPAÑIA 
FROM EMPLEADO WHERE ID_EMPLEADO NOT IN (
SELECT ID_EMPLEADO FROM EMPLEO_HAS_PROYECTO_HAS_DEPARTAMENTO
)

Esta query es transformable a:

SELECT NOMBRE, APELLIDOS, DNI, TELEFONO, ID_PUESTO, ID_COMPAÑIA 
FROM EMPLEADO 
WHERE ID_EMPLEADO EXISTS (
SELECT ID_EMPLEADO FROM EMPLEO_HAS_PROYECTO_HAS_DEPARTAMENTO
)

LEFT OUTER JOIN y chequear por la condición (si es un NOT IN se mirará que sea NULL)

La otra forma de convertir esta query es con un LEFT OUTER JOIN, chequeando que ese campo sea NULL.

De nuevo veamos con el mismo ejemplo la conversión a través del LEFT OUTER JOIN:

SELECT EMP.NOMBRE, EMP.APELLIDOS, EMP.DNI, 
EMP.TELEFONO, EMP.ID_PUESTO, EMP.ID_COMPAÑIA 
FROM EMPLEADO EMP LEFT JOIN EMPLEO_HAS_PROYECTO_HAS_DEPARTAMENTO EPD 
ON EMP.ID_EMPLEADO = EPD.ID_EMPLEADO 
WHERE EMP.ID_EMPLEADO IS NULL

Siempre que queramos comprobar solamente la existencia de un registro utilizaremos el EXISTS en vez del IN.

Si no es viable prescindir del operador IN debemos poner en la parte izquierda los valores más frecuentes de encontrar y al final de la lista los menos frecuentes.

¿Y el operador BETWEEN?

El operador BETWEEN comprueba que un valor se encuentre dentro de un rango, por lo que también puede sustituir en muchas ocasiones a la clausula IN y su rendimiento es mucho mejor. Siempre que podamos escoger, utilizaremos el operador BETWEEN.

SELECT ID_DEPARTAMENTO FROM DEPARTAMENTO WHERE ID_DEPARTAMENTO IN (1, 2, 3, 4)

Por:

SELECT ID_DEPARTAMENTO FROM DEPARTAMENTO WHERE ID_DEPARTAMENTO BETWEEN 1 AND 4

En el caso de que ID_DEPARTAMENTO tenga un índice (cosa casi segura porque es PK), al motor le resultará mucho más fácil calcular el resultado a través del operador BETWEEN.

Utilización del operador LIKE

Cuando utilicemos el operador LIKE debemos de intentar que nuestra cadena de búsqueda no comience jamás por una wildcard (%, *, etc), ya que en estos casos el operador no puede utilizar su índice, lo que le convierte en una clausula NON-SARGABLE y aumenta mucho más su coste.

Operador OR

En la primera pildorita os decíamos que una posible modificación para el UNION era usar OR, pero esto no siempre es verdad. Algunos motores de Bases de Datos como MySQL no utilizan los índices cuando hay operadores OR, por lo que a veces es mejor utilizar un UNION ALL a un OR.

Si tenéis dudas, lo mejor es tirar ambas queries y ver si vuestra tecnología tiene problemas de rendimiento con el OR.

Índice de Pildoritas

Share