Documente Academic
Documente Profesional
Documente Cultură
Vistas
PARTE I.
VISTAS
Tema 1. Vistas
Pgina 1
Lenguaje Sql con MySQL avanzado Parte I. Vistas
TEMA 1.
Vistas
Alberto Carrera Martn
Antes de empezar a trabajar asegrate que la base de datos est arrancada. Si utilizas
Windows XP podrs comprobarlo mediante:
En este caso se encuentra iniciado, si no fuera as lo podras arrancar haciendo clic con
el botn derecho sobre el servicio y eligiendo la opcin de Iniciar.
Botn Inicio / Todos los programas / MySQL / MySQL System Tray Monitor
aparecer con el siguiente icono en la barra de estado . Al hacer un clic con el botn
derecho sobre l se puede comprobar que la base de datos est corriendo o
ejecutndose tal y como se aprecia en la primera lnea de siguiente ilustracin 2. El
rectngulo verde del icono ya hace presagiar tal situacin; si la figura que nos
hubiramos encontrado dentro del icono hubiera sido un cuadrado rojo, entonces la base
de datos estara parada y por tanto deberamos arrancarla (opcin Start Instance en
ilustracin 3 siguiente)
Pgina 2
Lenguaje Sql con MySQL avanzado Parte I. Vistas
La realizaremos de dos maneras de las varias posibles existentes. Lee las dos y despus
pon en prctica la que desees (o puedes experimentar con las dos)
Nota: La unidad de disco anterior (C:) y la ruta de carpetas puede cambiar en funcin de
donde se realizara la instalacin.
Dentro de la carpeta anterior crea a su vez una carpeta denominada bases y copia all el
script tablas1.sql que encontrars en la seccin de materiales del curso. Una vez hecho,
arranca una ventana de consola (Botn Inicio / Todos los programas / Accesorios /
Smbolo de sistema), sitate en la carpeta anterior (C:\Archivos de
programa\MySQL\MySQL Server 5.0\bin>) y ejecuta el comando siguiente que te
permitir conectarte a la base de datos como usuario root y al mismo tiempo ejecutar
las instrucciones que contiene el script tablas1.sql copiado a la carpeta bases anterior:
El script tablas1.sql crea, adems de las tablas que puedes ver al final de este apartado,
un usuario1 de clave usuario1 con todos los permisos de trabajo sobre la base de datos
Pgina 3
Lenguaje Sql con MySQL avanzado Parte I. Vistas
Type 'help;' or '\h' for help. Type '\c' to clear the buffer.
Pgina 4
Lenguaje Sql con MySQL avanzado Parte I. Vistas
Observa que se ha
introducido el usuario y la
clave del Administrador root
pero no la base de datos a la
que se conecta (Default
Schema) por lo que tras
pulsar el botn OK puede
aparecer la siguiente
ilustracin 5 de la izquierda
pantalla para recordrnoslo:
Pulsaremos el botn Ignore para continuar y entrar en la herramienta cliente. Una vez
en ella abriremos (opcin File / Open Script del men) el script tablas1.sql que
podrs encontrar en la seccin de materiales del curso (ver ilustracin 6)
Pgina 5
Lenguaje Sql con MySQL avanzado Parte I. Vistas
usuario usuario1 de clave usuario1 y la base de datos prctica1 con las 3 tablas que la
componen (haciendo doble clic en cada una de ellas podrs ver sus registros)
Antes de definir lo que es una vista vamos a ver las ventajas que nos aportan.
Instruccin 1
Pgina 6
Lenguaje Sql con MySQL avanzado Parte I. Vistas
Instruccin 2
- Facilidad de uso para consultas complejas. Si un Jefe desea consultar los Centros
junto con sus Departamentos y nombres de los Directores:
Instruccin 3
Pgina 7
Lenguaje Sql con MySQL avanzado Parte I. Vistas
Instruccin 4
Instruccin 5
y con ello obtendr las 8 filas y 5 columnas anteriores con toda la informacin sobre
centros, departamentos y sus directores.
Instruccin 6
Hay que advertir que aunque el aspecto de una vista sea el de una tabla, una vista no es
nada ms que una instruccin SELECT del SQL almacenada con un nombre (vista1a,
vista1b). Por tanto no contiene datos (filas) permanentemente como una tabla y de
esta manera no hay ficheros asociados a ellas. De todas formas, como se puede
comprobar con la ltima instruccin lanzada, la forma de manejar vistas y tablas es muy
similar y podemos estar consultando un origen de datos sin saber si ste es una tabla o
una vista.
Pgina 8
Lenguaje Sql con MySQL avanzado Parte I. Vistas
Recuerda que las palabras reservadas que aparecen entre corchetes [] son opcionales. La
| indica elegir una opcin entre las posibles alternativas.
La sentencia anterior crea una nueva vista o reemplaza una existente (clusula OR
REPLACE) si esta ya existiera.
El creador de la vista, en este caso usuario1, debe estar autorizado para poder crear
vistas, es decir, poseer el privilegio CREATE VIEW. Si observas las lneas 4 y 5 del
script tablas1.sql con el que ests trabajando y que aparecen a continuacin, el
Administrador root se lo ha concedido, tanto este privilegio como todos los posibles:
Instruccin 7
El resto de clusulas de creacin de vistas:
Pgina 9
Lenguaje Sql con MySQL avanzado Parte I. Vistas
Ejemplos de utilizacin.
Notas:
- El nombre que le damos a las vistas en este tema, para su fcil localizacin, es
vista1a, vista1b... Realmente debemos utilizar nombres mucho ms
significativos que indiquen qu informacin va a presentar (como p.ej. los
utilizados en los ejemplos del apartado 6).
- Todos los ejemplos se ejecutan desde el browser teniendo seleccionada la base
de datos practica1 (ver ilustracin 7 anterior). De esta manera se omite la
seleccin de la misma (sentencia USE practica1) o preceder al nombre de cada
tabla o vista el nombre de la base de datos (SELECT * FROM
practica1.vista1a;).
Ejemplo1. Nombre y presupuesto de todos los departamentos del centro nmero 10:
Instruccin 8
Instruccin 9
Pgina 10
Lenguaje Sql con MySQL avanzado Parte I. Vistas
Instruccin 10
Posiblemente una vez creada no puedas ver la vista en el panel del esquema a no ser que
cierres el programa cliente grfico y vuelvas a entrar. Para evitar esto, selecciona con el
botn derecho la base de datos practica1 y elige la opcin de refrescar (Refresh) tal y
como aparece en la ilustracin 9:
Nombre, salario y nmero de departamento de los empleados que superan los 400 de
salario:
Instruccin 11
Ejemplo 3.
Instruccin 12
Ejemplo 4
Pgina 11
Lenguaje Sql con MySQL avanzado Parte I. Vistas
Instruccin 13
Ejemplo 5
Instruccin 14
Pgina 12
Lenguaje Sql con MySQL avanzado Parte I. Vistas
Si tuvieras acceso a varias bases de datos y slo quisieras saber las vistas de que
dispones en la base de datos practica1, la misma informacin anterior la podras
obtener:
Instruccin 15
Viendo las filas resultantes puedes comprobar que la columna TABLE_NAME contiene
el nombre de la vista y que la columna VIEW_DEFINITION la sentencia SELECT que
la construye. Por tanto si intentaras ver esta ltima columna solamente y para una vista
en concreto:
Instruccin 16
Lo que ocurre con la anterior consulta es que puedes encontrar una expresin un poco
confusa a la hora de mostrar la sentencia SELECT y adems en caso de que sta sea
larga no verse por completo y aparecer partida. Por eso quizs sea mejor seleccionar la
vista deseada del diccionario de datos, en concreto su columna VIEW_DEFINITION
(p.ej. de cualquiera de las vistas que aparece en la ilustracin 11 anterior) y con el
botn derecho elegir la opcin View Field in Popup Editor.
Tambin puedes conseguir ver completa la instruccin que construye la vista mediante
una ventana cliente (Tools / MySQL Command Line Client de la barra de mens) y el
comando:
Pgina 13
Lenguaje Sql con MySQL avanzado Parte I. Vistas
A travs de los conceptos aqu expuestos podrs comprender la funcionalidad del resto
de columnas de la tabla (vista) anterior.
1.4 Modificacin
La sintaxis bsica es muy similar a la de creacin:
ALTER
[ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE}]
[DEFINER = {nombreusuario} | CURRENT_USER}]
[SQL SECURITY {DEFINER | INVOKER}]
VIEW nombre_vista [(lista_columnas)]
AS sentencia_select
[WITH [CASCADED | LOCAL] CHECK OPTION]
Instruccin 17
1.5 Borrado
A partir de la version de MySql 5.0.1 como las anteriores sentencias. Sintaxis:
Borra una o ms vistas. Para poder realizarlo se debe poseer los privilegios de borrado
sobre vistas. La clusula IF EXISTS evita que aparezca mensaje de error en caso de
que la vista a borrar no exista y en su lugar aparece un mensaje informativo.
Pgina 14
Lenguaje Sql con MySQL avanzado Parte I. Vistas
Instruccin 18
Instruccin 19
Instruccin 20 Instruccin 21
Pgina 15
Lenguaje Sql con MySQL avanzado Parte I. Vistas
modificar datos de una tabla a travs de una vista? Muy sencillo, consultando el
diccionario de datos o lo que es lo mismo, la base de datos information_schema
Instruccin 22
Pgina 16
Lenguaje Sql con MySQL avanzado Parte I. Vistas
Instruccin 23
Pgina 17
Lenguaje Sql con MySQL avanzado Parte I. Vistas
Siempre que no nos dejemos de rellenar los campos obligatorios de la tabla base
podremos hacer inserciones a travs de la vista.
Instruccin 24
Instruccin 25
Lo que debes recordar es que siempre podremos realizar inserciones en las tablas a
travs de sus vistas siempre y cuando no nos dejemos los campos obligatorios de la
tabla. Deberemos tener en cuenta adems de la anterior todas las restricciones que
aparecen al final del apartado b anterior.
Antes de terminar el tema comentar una opcin que puede aadir cierta seguridad a las
vistas y que se haba dejado planteada en el apartado 1.3 de este tema en relacin a la
creacin de vistas y su sintaxis bsica. La clusula es:
Instruccin 26
La sentencia anterior crea una vista con todos los datos de los empleados del
Departamento 100. A travs de esta vista, como se ha trabajado en los puntos anteriores
se puede realizar cualquier operacin de manipulacin de la tabla base empleados. Por
eso, estas dos instrucciones son totalmente correctas:
Pgina 18
Lenguaje Sql con MySQL avanzado Parte I. Vistas
Instruccin 27
Instruccin 28
Pero en la segunda de ellas, hemos utilizado una vista que representa los empleados del
Departamento 100 para introducir un empleado que no cumple realmente la clusula
WHERE del SELECT de creacin de la vista ya que su departamento es el 120.
Si hubiramos creado la vista de esta otra forma (se ha aadido la comprobacin al
final):
Instruccin 29
no hubiramos tenido problemas en aadir al empleado Mario Carrera por ser del
Departamento 100 pero no nos hubiera dejado realizar la insercin de la empleada
Carmen Bailn dando mensaje de error ya que antes de hacer la insercin MySQL
chequea que los datos a introducir cumplan con la seleccin de la clusula WHERE de
la sentencia SELECT de creacin de la vista que seleccionaba las filas de empleados del
Departamento 100 y estamos intentando introducir una empleada de otro Departamento.
Recordad que tal y como se expuso en el apartado 1.3, la clusula WITH CHECK
OPTION equivale a WITH CASCADED CHECK OPTION en caso de que no se
especifique la opcin LOCAL, al ser CASCADED la opcin por defecto, y por tanto
todas las vistas que se creen a partir de la vista vista1i debern seguir respetando las
restricciones de la clusula WHERE de esta ltima.
Instruccin 30
Ilustracin 15. Resultado de la Instruccin 30
Pgina 19
Lenguaje Sql con MySQL avanzado Parte I. Vistas
Instruccin 33
Pgina 20
Lenguaje Sql con MySQL avanzado Parte II. Programas almacenados
PARTE II.
PROGRAMAS ALMACENADOS
2.1. Introduccin...................................................................................................3
2.2. Ventajas de su utilizacin..............................................................................3
2.3. Edicin de programas....................................................................................4
2.4. Fundamentos bsicos del lenguaje ................................................................8
2.4.1. Variables, tipos de datos, comentarios y literales.................................8
2.4.2. Variables de usuario ...........................................................................12
2.4.3. Parmetros ..........................................................................................13
2.4.4. Principales operadores........................................................................15
2.4.5. Expresiones.........................................................................................16
2.4.6. Funciones incorporadas ......................................................................17
2.4.7. Bloques de instrucciones ....................................................................20
2.4.8. El comando IF ....................................................................................22
2.4.9. El comando CASE..............................................................................24
2.4.10. El comando LOOP, LEAVE e ITERATE ........................................25
2.4.11. El comando REPEAT UNTIL.....................................................26
2.4.12. El comando WHILE .........................................................................27
2.4.13. Bucles anidados ................................................................................28
2.5. Procedimientos ............................................................................................28
2.5.1. Creacin de Procedimientos. Diccionario de datos ............................28
2.5.2. Modificacin de Procedimientos ........................................................31
2.5.3. Borrado de Procedimientos ................................................................32
2.5.4. Utilizacin de instrucciones DDL y DML
en procedimientos almacenados ........................................................32
2.5.5. Utilizacin de instrucciones de consulta
en procedimientos almacenados ........................................................32
2.5.6 Almacenar en variables el valor de una fila de una tabla ....................33
2.5.7 Sentencias preparadas. SQL dinmico ................................................35
2.6. Cursores.......................................................................................................38
2.6.1. Sentencias utilizadas con cursores. Ejemplos ....................................38
2.6.2. Cursores anidados...............................................................................43
2.7. Manejo de errores........................................................................................44
2.7.1 Introduccin a la gestin de errores..................................................44
2.7.2 Tipos de manejador ..........................................................................48
2.7.3 La condicin del manejador .............................................................49
2.7.4 Orden de actuacin del manejador ...................................................52
2.7.5 mbito de actuacin del manejador .................................................53
2.7.6 Ejemplo de tratamiento de errores....................................................54
2.8 Funciones....................................................................................................55
2.8.1 Creacin de funciones. Diccionario de datos ...................................55
2.8.2 Ejemplos de utilizacin de Funciones ..............................................56
2.8.3 Modificacin de funciones ...............................................................60
2.9 Triggers.......................................................................................................60
2.9.1 Creacin de triggers. Diccionario de datos.......................................60
Pgina 1
Lenguaje Sql con MySQL avanzado Parte II. Programas almacenados
Pgina 2
Lenguaje Sql con MySQL avanzado Parte II. Programas almacenados
TEMA 2
Programas almacenados en MySQL
Alberto Carrera Martn
2.1 Introduccin
La aparicin de los procedimientos almacenados, funciones y triggers
(desencadenadores) en MySQL 5 ha supuesto una enorme revolucin en este gestor de
bases de datos que ya disfrutaba de una gran popularidad. Se ha producido el salto para
que MySQL pueda ser utilizado como SGBD empresarial. A ello hay que aadir que la
sintaxis de los programas es sencilla lo que facilita su escritura.
Pgina 3
Lenguaje Sql con MySQL avanzado Parte II. Programas almacenados
Como hemos hecho con el tema anterior de vistas, utilizaremos la herramienta MySQL
Query Browser porque presenta mayores ventajas como ayuda incorporada, posibilidad
de ejecutar sentencias SQL o la visualizacin de palabras clave del lenguaje resaltadas
en diferentes colores entre otras caractersticas.
Pgina 4
Lenguaje Sql con MySQL avanzado Parte II. Programas almacenados
DELIMITER $$
DROP PROCEDURE IF EXISTS ejemplo1 $$
CREATE PROCEDURE ejemplo1 ()
BEGIN
SELECT 'Mi primer programa en MySQL';
END$$
DELIMITER ;
Breve explicacin: MySQL utiliza el carcter ; para finalizar cada sentencia SQL.
Como dentro del cuerpo del procedimiento las instrucciones van separadas por ;
(5 lnea) para distinguirlas de las sentencias SQL necesitamos utilizar otro carcter
delimitador (en la 1 lnea se habilita y en la ltima se vuelve a dejar el que estaba).
La sentencia DROP PROCEDURE. borra el procedimiento si este estuviera
previamente creado (de no ponerlo dara error); en la 3 lnea se crea dicho
procedimiento.
La 4 lnea indica el comienzo del cuerpo del procedimiento que finaliza en la
penltima lnea.
Pgina 5
Lenguaje Sql con MySQL avanzado Parte II. Programas almacenados
4. Pulsa el botn Guardar o comando del men File / Save Nombre del script:
ejemplo1.
5. Para compilar el procedimiento anterior en busca de posibles errores (no es el
caso si lo has copiado igual que aqu aparece) elige la opcin de men Script /
Execute o el botn Execute (botn verde de la parte superior derecha de la
ilustracin 2 anterior). Si no te apareciera su nombre (ejemplo1) o cualquier otro
objeto que crees en adelante en la pestaa Schemata tal y como figura en la
ilustracin 2 anterior, selecciona la base de datos test y con el botn derecho la
opcin Refresh (refrescar):
Pgina 6
Lenguaje Sql con MySQL avanzado Parte II. Programas almacenados
Procedimiento 1 ejemplo1_bis
y vers que slo tienes que escribir en la lnea 6 que est vaca la instruccin:
Pgina 7
Lenguaje Sql con MySQL avanzado Parte II. Programas almacenados
- Si no aparece en pantalla, utiliza el comando File / Open Script del men para
abrir el script que contiene el programa almacenado.
- Modifica las lneas de cdigo necesarias.
- Volver a guardarlo con la opcin del men File / Save.
- Sigue los mismos pasos vistos para compilarlo y ejecutarlo.
SINTAXIS:
Pgina 8
Lenguaje Sql con MySQL avanzado Parte II. Programas almacenados
De la sintaxis anterior se deduce que se pueden declarar varias variables del mismo tipo
seguidas y separadas por comas. Al mismo tiempo que se declaran las variables se
pueden definir asignndoles un valor inicial mediante la clusula DEFAULT; si no se
les asigna ninguno entonces las variables quedan definidas al valor NULL. En el
momento de la declaracin hay que indicar el tipo de datos de la variable; pueden
utilizarse cualquiera de los que se emplean en el momento de crear tablas mediante la
instruccin CREATE TABLE. Veremos los que se utilizan ms frecuentemente.
Pgina 9
Lenguaje Sql con MySQL avanzado Parte II. Programas almacenados
Procedimiento 2 variables1
Procedimiento 3 variables2
Pgina 10
Lenguaje Sql con MySQL avanzado Parte II. Programas almacenados
Las reglas para nombrar variables son bastante flexibles pues a diferencia de otros
lenguajes se permite:
Todas las variables que se pueden utilizar deben ser escalares, es decir, un solo valor, a
diferencia de otros lenguajes que permiten definir variables basadas en tipos de datos
compuestos como son los registros, arrays
Procedimiento 4 asigna1
Pgina 11
Lenguaje Sql con MySQL avanzado Parte II. Programas almacenados
Procedimiento 5 variables3
Este tipo de variables no necesitan declaracin y van precedidas del carcter @. Son de
un tipo de datos variant y pueden almacenar texto, fechas y nmeros. En las siguientes
lneas se crea una variable de usuario de nombre v1, se inicializa a 20 y a continuacin
se llama (CALL) al programa variables3 que lo que hace es doblar el valor de la
variable como se puede comprobar tanto en las lneas de procedimiento como en la
ventana de ejecucin desde la lnea de comandos de MySQL:
Su alcance es de una sesin y por tanto son accesibles desde cualquier programa que se
ejecuta durante esa sesin, lo que las asemeja al concepto de variables globales como se
muestra en el siguiente ejemplo:
Procedimiento 7 variables5
Procedimiento 6 variables4
Pgina 12
Lenguaje Sql con MySQL avanzado Parte II. Programas almacenados
2.4.3 Parmetros
Los parmetros son variables que se envan y reciben de los programas a los que se
llaman.
Los tipos de parmetros, segn el modo en que se pasan al procedimiento llamado son:
Procedimiento 8 parametro1
Pgina 13
Lenguaje Sql con MySQL avanzado Parte II. Programas almacenados
Procedimiento 9 parametro2
Pgina 14
Lenguaje Sql con MySQL avanzado Parte II. Programas almacenados
Procedimiento 10 parametro3
Ejecutando el procedimiento parametro3:
OPERADORES MATEMTICOS
+ Suma
- Resta
* Multiplicacin
/ Divisin
DIV Divisin entera
% Resto
Procedimiento 11 operadores1
Pgina 15
Lenguaje Sql con MySQL avanzado Parte II. Programas almacenados
OPERADORES DE COMPARACIN.
Comparan dos valores y devuelven como resultado CIERTO (1), FALSO (0) O
NULO (NULL))
OPERADOR SIGNIFICADO EJEMPLO Y RESULTADO
> Mayor que 3 > 2 Cierto
< Menor que 4 < 6 Cierto
<= Menor o igual que 4 <= 3 Falso
>= Mayor o igual que 4>=3 Cierto
= Igual a 4 = 4 Cierto
< > != Distinto de 4 <> 4 Falso
<=> Comparacin de valores nulos. NULL <=> NULL Cierto
Devuelve cierto si ambos valores son
nulos
BETWEEN Comprendido entre dos valores 45 BETWEEN 25 AND 50
Cierto
IS NULL Si valor nulo 3 IS NULL Falso
IS NOT NULL Si valor no nulo 3 IS NOT NULL Cierto
NOT No comprendido entre dos valores 45 NOT BETWEEN 25 AND
BETWEEN 50 Falso
IN Pertenencia al conjunto o lista 45 IN (44, 45, 46) Cierto
NOT IN No pertenencia al conjunto o lista 45 NOT IN (44, 45, 46)
Falso
LIKE Coincidencia con patrn de "ALBERTO CARRERA"
bsqueda LIKE "%CARRERA"
Cierto
2.4.5 Expresiones
Se trata de una combinacin de literales, variables y operadores que se evalan para
devolver un valor.
Pgina 16
Lenguaje Sql con MySQL avanzado Parte II. Programas almacenados
FUNCIONES DE CADENA
FUNCIN DEVUELVE EJEMPLO Y
RESULTADO
LIKE(plantilla) Resultado de comparar una cadena SELECT 'ALBERTO' LIKE
con una plantilla 'ALBER%' 1 (cierto)
NOT LIKE Lo contrario a la fila anterior SELECT 'ALBERTO' NOT
(plantilla) LIKE 'ABIERTO' 1
_ (subrayado) Se trata de un comodn que SELECT 'ALBERTO' LIKE
reemplaza un carcter en una 'ALBERT_' 1
cadena
% Como el caso anterior pero para SELECT 'ALBERTO' LIKE
uno o ms caracteres 'ALBER%' 1 (cierto)
\ Como en otros lenguajes se trata del SELECT '30%' LIKE '30\%'
carcter de escape, si precede al 1
comodn elimina su funcin y lo
trata como un carcter ms
Pgina 17
Lenguaje Sql con MySQL avanzado Parte II. Programas almacenados
FUNCIONES DE FECHA
FUNCIN DEVUELVE EJEMPLO Y RESULTADO
NOW() Fecha y hora segn el SELECT NOW() 2006-08-01
formato aaaa-mm-dd 00:40:25
hh:mm:ss
DAYOFWEEK(fecha) Cifra que representa el SELECT DAYOFWEEK('1966-
da de la semana (1 11-03') 5 |
domingo, 2 lunes)
WEEKDAY(fecha) dem de DAYOFWEEK SELECT WEEKDAY('1966-11-
pero con otros valores: 0 03') 3
lunes, 1 martes
DAYOFMONTH(fecha) Da del mes (entre 1 y SELECT
31) DAYOFMONTH('1966-11-03')
3
DAYOFYEAR(fecha) Da del ao (entre 1 y SELECT DAYOFYEAR('1966-
366) 11-03') 307
MONTH(fecha); Mes del ao (entre 1 y SELECT MONTH('1966-11-03')
12) 11
DAYNAME(fecha) Nombre del da de la SELECT DAYNAME('1966-11-
fecha 03') Thursday
MONTHNAME(fecha) Nombre del mes SELECT MONTHNAME('1966-
11-03') November
QUARTER(fecha) Trimestre del ao (entre SELECT QUARTER('1966-11-
1 y 4) 03') 4
WEEK(fecha [,inicio]) Semana del ao (entre 1 SELECT WEEK('2006-12-20',1)
51
y 52). Inicio especifica el
comienzo de la semana.
Si no se especifica vale 0
(domingo). Para empezar
el lunes utilizar el 1
YEAR(fecha) Ao (entre 1000 y 9999) SELECT YEAR('2006-12-20')
2006
HOUR(fecha) La hora SELECT HOUR(NOW()) 1
MINUTE(fecha) Los minutos SELECT MINUTE(NOW()) 5
SECOND(fecha) Los segundos SELECT SECOND(NOW())
58
Pgina 18
Lenguaje Sql con MySQL avanzado Parte II. Programas almacenados
FUNCIONES DE CONTROL
FUNCIN DESCRIPCIN EJEMPLO Y
RESULTADO
IF(expr1, expr2, expr3) Si la expresin expr1 es cierta, SET @A=20; SET
devuelve expr2, sino expr3 @B=15;
SELECT IF(@A<@B,
@A+@B, @A - @B);
5
IFNULL(expr1, expr2) Si la expresin expr1 es NULL SET @A=20;
devuelve expr2, sino expr1 SELECT IFNULL(@A,
0); 20
NULLIF(expr1, expr2) Si la expresin expr1 es igual a SET @A=20; SET
expr2, devuelve NULL sino @B=15;
expr1
SELECT NULLIF(@B,
@A); 15
CASE valor WHEN Compara el valor con cada una de SELECT CASE
comp1 THEN res1 las expresiones comp. Si se WEEKDAY(NOW())
[WHEN comp2 THEN verifica la igualdad entonces WHEN 5 THEN 'Fin de
res2] [ELSE reselse] devuelve el valor res asociado, en semana'
END cualquier otro caso devuelve WHEN 6 THEN 'Fin de
reselse semana'
ELSE 'No es fin de
semana'
END;
Pgina 19
Lenguaje Sql con MySQL avanzado Parte II. Programas almacenados
FUNCIONES DE AGREGACIN
FUNCIN DEVUELVE EJEMPLO Y
RESULTADO
AVG(columna) Media de los valores de la columna SELECT AVG(salario)
especificada FROM empleados
302.9412
COUNT Nmero de valores no nulos de la SELECT
(columna | *) columna (si esta se especifica como COUNT(comision)
argumento). Utilizando el carcter * FROM empleados 14
devuelve el nmero total de valores SELECT COUNT(*)
incluyendo los nulos FROM empleados 34
(luego 20 trabajadores no
tienen comisin)
MIN(columna) Valor mnimo de la columna SELECT MIN(salario)
FROM empleados 100
MAX(columna) Valor mximo de la columna SELECT MAX(salario)
FROM empleados 720
SUM(columna) Suma de valores contenidos en la SELECT SUM(salario)
columna FROM empleados
10300
OTRAS FUNCIONES
FUNCIN DESCRIPCIN EJEMPLO Y
RESULTADO
CAST (expresin AS Convierte la expresin al tipo SELECT
tipo) indicado CONVERT(20060802,
CONVERT DATE) 2006-08-02
(expresin, tipo)
LAST_INSERT_ID() Devuelve el valor creado por SELECT
una columna de tipo LAST_INSERT_ID() 0
AUTO_INCREMENT en la
ltima insercin
VERSION() Devuelve la versin del servidor SELECT VERSION()
MySQL 5.0.20a-nt
CONNECTION_ID() Devuelve el identificador de SELECT
conexin CONNECTION_ID() 4
DATABASE() Devuelve la base de datos actual SELECT DATABASE()
test
USER() Devuelve el usuario actual SELECT USER()
root@localhost
Pgina 20
Lenguaje Sql con MySQL avanzado Parte II. Programas almacenados
Un bloque no solo agrupa instrucciones sino tambin otros elementos que se tratan en
este curso como:
1. Declaracin de variables y condiciones.
2. Declaracin de cursores.
3. Declaracin de manejadores de error.
4. Cdigo de programa.
Como ocurre con otros lenguajes de programacin, los bloques pueden etiquetarse. Esta
forma de actuar garantiza una fcil lectura del procedimiento y por tanto de su
mantenimiento y permite abandonar el bloque antes de que este concluya si as fuera
necesario (sentencia LEAVE). Sintaxis:
[etiqueta:] BEGIN
Declaracin de variables y condiciones.
Declaracin de cursores.
Declaracin de manejadores de error.
Cdigo de programa.
END [etiqueta];
Ejemplos de aplicacin:
Procedimiento 12 bloque1
Pgina 21
Lenguaje Sql con MySQL avanzado Parte II. Programas almacenados
Procedimiento 13 bloque2
Procedimiento 14 bloque3
Procedimiento 15 bloque4
2.4.8 El comando IF
Igual en su funcionamiento que otros lenguajes de programacin. Ejecuta la accin cuya
expresin (condicin) es cierta (de no ser cierta ninguna entonces ejecuta la accin
asociada a la sentencia ELSE).
Sintaxis:
Pgina 22
Lenguaje Sql con MySQL avanzado Parte II. Programas almacenados
Ejemplo:
Procedimiento 16 condicional1
El valor inicial (lnea 6) de la variable v_edad conduce a que la instruccin que se
ejecute sea la de la lnea 12 al no cumplir ninguna de las dos condiciones anteriores.
El ejemplo que viene a continuacin nos sirve para ver una versin ms abreviada de
la sentencia condicional que la del ejemplo anterior as como para sealar el
comportamiento de la sentencia condicional ante valores nulos.
Procedimiento 17 condicional2
En este caso se ejecutar la instruccin 10 puesto que la edad contiene un valor nulo que
no hace cierta la expresin de la lnea 7. Hay que tener cuidado pues se est asignando
el calificativo de adulto a una persona de la que se desconoce su edad. Para estos
casos puede utilizarse la forma ms simple de la sentencia condicional:
Pgina 23
Lenguaje Sql con MySQL avanzado Parte II. Programas almacenados
Procedimiento 18 condicional3
CASE expresin
WHEN valor1 THEN
instrucciones
[WHEN valor2 THEN
instrucciones ...]
[ELSE
instrucciones]
END CASE;
Procedimiento 19 condicional4
Pgina 24
Lenguaje Sql con MySQL avanzado Parte II. Programas almacenados
CASE
WHEN condicin1 THEN
instrucciones
[WHEN condicin2 THEN
instrucciones ...]
[ELSE
instrucciones]
END CASE;
Ejemplo:
Procedimiento 20 condicional5
[etiqueta:] LOOP
instrucciones
END LOOP [etiqueta];
Todas las instrucciones comprendidas entre las palabras reservadas LOOP Y END
LOOP (bucle), se ejecutan un nmero de veces hasta que la ejecucin del bucle se
encuentra con la instruccin:
LEAVE etiqueta
Pgina 25
Lenguaje Sql con MySQL avanzado Parte II. Programas almacenados
Procedimiento 21 bucle1
La sentencia:
ITERATE etiqueta
se utiliza para forzar que la ejecucin del bucle termine en el momento donde se
encuentra con esta instruccin y contine por el principio del bucle. De esta manera en
el ejemplo que viene a continuacin se ejecutar 3 veces la instruccin de la lnea 13
(para los valores de i del 1 al 4 excepto el 3)
Procedimiento 22 bucle2
Pgina 26
Lenguaje Sql con MySQL avanzado Parte II. Programas almacenados
Las instrucciones se ejecutarn hasta que sea cierta la expresin. Por lo menos el
conjunto de instrucciones se ejecuta una vez pues la evaluacin de la expresin se hace
posterior a la ejecucin de las instrucciones. El mismo procedimiento bucle1 anterior
pero utilizando esta otra instruccin quedara:
Procedimiento 23 bucle3
Equivale a la sentencia iterativa vista anteriormente
etiqueta: LOOP
instrucciones
IF expresin THEN LEAVE etiqueta; END IF;
END LOOP etiqueta;
Procedimiento 24 bucle4
Pgina 27
Lenguaje Sql con MySQL avanzado Parte II. Programas almacenados
etiqueta: LOOP
IF !expresin THEN LEAVE etiqueta; END IF;
resto de instrucciones;
END LOOP etiqueta;
Procedimiento 25 bucle5
Al ejecutar el ejemplo anterior se visualizarn los valores i-j: 1-1, 1-2, 2-1, 2-2
2.5 Procedimientos
2.5.1 Creacin de procedimientos. Diccionario de Datos
La sintaxis completa de creacin de procedimientos es:
Pgina 28
Lenguaje Sql con MySQL avanzado Parte II. Programas almacenados
Para crear un procedimiento o funcin el usuario debe disponer del privilegio CREATE
ROUTINE y el de ALTER ROUTINE para modificarlo o borrarlo; este ltimo
privilegio se asigna automticamente al creador del procedimiento o funcin. Para poder
ejecutar un procedimiento o funcin debe disponerse del privilegio EXECUTE.
1. El nombre del procedimiento cumple con las normas vistas en este captulo
referidas a nombrar variables. La lista de argumentos suministrados al
procedimiento tambin ha sido estudiada.
2. La clusula LANGUAGE SQL indica que el lenguaje utilizado en los
procedimientos cumple el estndar SQL:PSM. Es una clusula innecesaria en
este momento pues los procedimientos en MySQL slo soportan este estndar.
Si MySQL en un futuro aceptara la escritura de procedimientos almacenados en
otros lenguajes como C o Java entonces ya sera necesario indicar el lenguaje de
programacin utilizado en el procedimiento.
3. [NOT] DETERMINISTIC. Referido al comportamiento del procedimiento. Si
un procedimiento es DETERMINISTIC, siempre ante una misma entrada
devuelve una misma salida. Funciones numricas como el valor absoluto,
cuadrado, raz cuadrada son DETERMINISTIC pues siempre devuelven el
mismo resultado ante un mismo valor. Por otro lado, una funcin que devolviera
el nmero de das transcurridos desde 1900 hasta la fecha sera NOT
DETERMINISTIC pues cambia segn el da que se ejecuta. Por defecto la
opcin es NOT DETERMINISTIC. Al igual que la anterior se puede prescindir
de su utilizacin debido a que por el momento no es tenida en cuenta por el
servidor. Ms adelante podr ser utilizada para la optimizacin de consultas.
4. [{CONTAINS SQL | MODIFIES SQL DATA | READS SQL DATA | NO
SQL}] Indica el tipo de acceso que realizar el procedimiento a la base de
datos, si slo se va a leer datos se especificar la clusula READ SQL DATA, si
adems de ello los modifica entonces la clusula MODIFIES SQL DATA ser la
que se emplee. Si el procedimiento no realiza ningn tipo de acceso a la base de
datos puede utilizarse la clusula NO SQL. Por defecto se utiliza la opcin
CONTAINS SQL que indica que el procedimiento contiene consultas SQL.
Estos parmetros se utilizan para mejorar el rendimiento.
5. [SQL SECURITY {DEFINER | INVOKER}] Indica si el procedimiento
almacenado se ejecutar con los permisos del usuario que lo cre (DEFINER) o
con los permisos del usuario que llama al procedimiento (INVOKER) La opcin
por defecto es DEFINER. Hay que tener muy en cuenta que con la opcin
DEFINER un usuario que lance el procedimiento podr acceder a los datos
aunque no posea los privilegios sobre las tablas que almacenan dichos datos; se
trata de un mecanismo de acceso a los procedimientos sin dar directamente
acceso a los datos.
6. [COMMENT comentario] Comentario sobre el procedimiento que puede ayudar
al usuario a conocer/recordar el funcionamiento del procedimiento. Esta
informacin puede consultarse como se ha visto anteriormente en el diccionario
de datos. Puede prescindirse de dicha clusula y realizar la escritura de los
comentarios aclaratorios al principio del bloque de instrucciones del
procedimiento utilizando los caracteres /* */ o --
Pgina 29
Lenguaje Sql con MySQL avanzado Parte II. Programas almacenados
Sintaxis:
Ejemplo:
El comando:
Pgina 30
Lenguaje Sql con MySQL avanzado Parte II. Programas almacenados
Instruccin 1
Pgina 31
Lenguaje Sql con MySQL avanzado Parte II. Programas almacenados
Procedimiento 26 procedimiento1
Pgina 32
Lenguaje Sql con MySQL avanzado Parte II. Programas almacenados
Procedimiento 27 resultset1
Ejemplo de ejecucin:
Procedimiento 28 resultset2
El tiempo de vida de las tablas temporales es el tiempo de duracin de la sesin.
Pgina 33
Lenguaje Sql con MySQL avanzado Parte II. Programas almacenados
las dos) y en la lnea 9 se indica donde (variables) se guardarn los valores de dichas
columnas segn el orden en que aparecen (el valor de la columna id se guardar en la
variable v_id, el de la columna alumno en la variable v_alumno).
Procedimiento 29 - procedimiento2
En el anterior ejemplo no ha habido ningn problema de ejecucin pues cada una de las
dos variables almacena slo un tem (el de la correspondiente columna), pues la
consulta slo devuelve una fila.
Pgina 34
Lenguaje Sql con MySQL avanzado Parte II. Programas almacenados
Procedimiento 30 - "procedimiento4"
donde el texto_sql contiene marcadores (carcter ?) para representar los valores que se
utilizarn en el momento de ejecutar la instruccin SQL.
La sentencia preparada anterior se ejecuta mediante:
donde la clusula USING se encarga de suministrar los valores para los marcadores
especificados en la sentencia PREPARE. La forma de especificar estos valores es en
forma de variables de usuario (prefijo @ ).
La sentencia preparada se puede eliminar mediante:
Pgina 35
Lenguaje Sql con MySQL avanzado Parte II. Programas almacenados
Procedimiento 31 sql_dinamico1
Pgina 36
Lenguaje Sql con MySQL avanzado Parte II. Programas almacenados
El SQL dinmico no se usa muy a menudo y debe utilizarse slo en los casos en que sea
necesario debido a que es ms complejo y menos eficiente que el SQL esttico. Debe
emplearse para realizar tareas o implementar utilidades que no pueden realizarse de otra
manera. Un ejemplo muy caracterstico de su empleo por su grado de optimizacin y
rapidez es para encontrar filas a partir de mltiples criterios de bsqueda:
Procedimiento 32 sql_dinamico2
Para averiguar los empleados del departamento 121 contratados antes de la dcada de
los 60 cuyo salario sea superior a 300:
Pgina 37
Lenguaje Sql con MySQL avanzado Parte II. Programas almacenados
2.6 Cursores
Es el instrumento que se utiliza cuando la sentencia SQL dentro del programa devuelve
ms de una fila como hemos visto en el apartado anterior.
De esta manera, un cursor es una zona de memoria que contiene un conjunto de filas
resultantes de una sentencia SQL con la ventaja de que podremos recorrer, visualizar y
manipular una a una cada una de esas filas.
Sintaxis:
Un aspecto muy importante a tener en cuenta es que los cursores se declaran en los
procedimientos u otros programas almacenados despus de la declaracin de variables,
no hacerlo as producir una situacin de error.
Procedimiento 33 cursor1
Pgina 38
Lenguaje Sql con MySQL avanzado Parte II. Programas almacenados
Recuperacin de las filas del cursor. Clusula FETCH (lnea 14): Cada vez
que se ejecuta recupera la siguiente fila a la que apunta el cursor y avanza el
puntero una posicin. Cada fila recuperada la va almacenando en las variables
v_id y v_alumno.
Cierre del cursor: Clusula CLOSE (lnea 19). Desactiva el cursor liberando la
zona de memoria ocupada por el cursor.
Puedes ver una ejecucin ms clara del procedimiento anterior abriendo una ventana
cliente sin salir de la herramienta MySQL Query Browser mediante la opcin de men
Tools / MySQL Command Line Client:
+------+----------+
| v_id | v_alumno |
+------+----------+
| 2 | alumno 2 |
+------+----------+
1 row in set (0.01 sec)
ERROR 1329 (02000): No data - zero rows fetched, selected, or
processed
Qu ha ocurrido realmente?
Pgina 39
Lenguaje Sql con MySQL avanzado Parte II. Programas almacenados
Recuadro 2: Primera vez que se ejecuta en el bucle la sentencia FETCH (lnea 14). Se
recupera la siguiente fila apuntada por el cursor, en este caso la primera, almacenando el
valor de la primera columna (1) en la variable v_id y el valor de la segunda columna
(alumno1) en la variable v_alumno. El puntero del cursor avanza una posicin.
Antes de finalizar el bucle se muestran los valores de las variables (lnea 17)
Recuadro 4: Tercera vez que se ejecuta en el bucle la sentencia FETCH (lnea 14). Se
intenta recuperar la siguiente fila apuntada por el cursor pero no hay ninguna fila que
recuperar pues el cursor ha finalizado, por tanto se produce la situacin de error:
Pgina 40
Lenguaje Sql con MySQL avanzado Parte II. Programas almacenados
Procedimiento 34 cursor2
Pgina 41
Lenguaje Sql con MySQL avanzado Parte II. Programas almacenados
El mismo recorrido del cursor pero con la instruccin iterativa REPEAT UNTIL:
Es muy habitual que las filas a recuperar del cursor dependan de un dato que se pasa
como argumento. El procedimiento siguiente es el mismo que el procedimiento cursor2
salvo que el nmero de filas a recuperar viene determinado por el parmetro p_id que se
le pasa al procedimiento (lnea 4) y por tanto tambin se modifica la lnea 12:
Pgina 42
Lenguaje Sql con MySQL avanzado Parte II. Programas almacenados
Procedimiento 37 cursor2_1
La llamada al procedimiento:
Pgina 43
Lenguaje Sql con MySQL avanzado Parte II. Programas almacenados
El procedimiento quedara:
Procedimiento 38 cursor5
Es muy importante sealar en el procedimiento anterior y cuando se utilicen cursores
anidados que antes de leer una nueva fila del cursor externo, hay que resetear la variable
utilizada para controlar el final del cursor (lnea 38) para que el final del cursor interno
no provoque un final del cursor externo sin haber terminado este ltimo.
Antes de terminar este apartado indicar que existe un tipo especial de cursores de
actualizacin que se tratan en el tema siguiente de transacciones.
Pgina 44
Lenguaje Sql con MySQL avanzado Parte II. Programas almacenados
Una handler es un bloque de instrucciones SQL que se ejecuta cuando se verifica una
condicin tras una excepcin (error) generada por el servidor.
Sintaxis:
Procedimiento 39 error1
Pgina 45
Lenguaje Sql con MySQL avanzado Parte II. Programas almacenados
se puede comprobar viendo la tabla o realizando una consulta que aade al anterior
alumno.
Tomando nota del nmero de error y modificando el anterior procedimiento para aadir
dicho control de error:
Procedimiento 40 error2
Resaltar que el error ha sido tratado y por tanto no finaliza la ejecucin del programa en
el momento en que se produce y si hubiera ms lneas de cdigo detrs de la lnea 9,
stas se ejecutaran debido al tipo de manejador, CONTINUE; esto no ocurrira si el
error no fuera tratado como hemos comprobado en el procedimiento error1 anterior
Pgina 46
Lenguaje Sql con MySQL avanzado Parte II. Programas almacenados
Procedimiento 41 error3
Llegados a este punto podemos utilizar un tercer argumento en el procedimiento, un
parmetro de tipo OUT, para que acte como flag o indicador de cmo ha ido la
ejecucin del procedimiento:
Procedimiento 42 error4
Llamando al anterior procedimiento error4 desde el interior de otro (lnea 7 de error5):
Procedimiento 43 error5
La primera ejecucin del procedimiento: CALL error5( ) funcionar correctamente,
apareciendo como fila/columna resultante : Alumno dado de alta.
La segunda ejecucin del mismo procedimiento anterior tambin funcionar
correctamente pues la situacin de error de cdigo repetido es tratada y por tanto el
programa finaliza correctamente y visualiza por pantalla que el nmero de matrcula ya
existe.
Volviendo otra vez a la declaracin de un manejador, hemos visto que tiene 3 partes que
pasaremos a ver a continuacin ms en detalle:
Pgina 47
Lenguaje Sql con MySQL avanzado Parte II. Programas almacenados
En ambos casos el error es tratado por lo que la ejecucin del programa puede
considerarse correcta y antes de realizarse la opcin CONTINUE o EXIT se ejecuta el
conjunto de instrucciones asociados al manejador.
Pgina 48
Lenguaje Sql con MySQL avanzado Parte II. Programas almacenados
dar como resultado una aviso indicando que ese nmero de matrcula ya existe. Al
intentar hacer la insercin de la lnea 10 el procedimiento provoca una situacin de error
(igual que para el caso anterior de la clusula EXIT) que es tratada inmediatamente
despus en el manejador de error poniendo a 1 el valor de la variable v_clave_repetida;
por tanto, al ser tratado el error y de forma continua (clusula CONTINUE lnea 8) la
ejecucin del procedimiento continua por la lnea 11 haciendo cierta la condicin y
avisando de la duplicidad de dicha matrcula.
Pgina 49
Lenguaje Sql con MySQL avanzado Parte II. Programas almacenados
Cul utilizar de los dos anteriores? En teora el segundo permitira una mayor
portabilidad a otros gestores de bases de datos pero en la prctica los lenguajes de
programacin para Oracle y Microsoft SQL Server son incompatibles con el de MySQL
por lo que no hace muy atractivo el uso de esta segunda opcin (DB2 de IBM es algo
compatible pues tanto DB2 como MySQL estn basados en el estndar SQL:2003).
Adems hay cdigos SQLSTATE que no corresponden con un cdigo de error de
MySQL sino a varios (para estos casos se utiliza el SQLSTATE genrico HY000)
Por lo anteriormente expuesto seguiremos utilizando en este curso los cdigos propios
de error de MySQL.
2. Mirando el manual, suele venir una tabla detallada de errores con su nmero y
descripcin en un apndice dedicado.
SQLEXCEPTION
SQLWARNING
NOT FOUND
Pgina 50
Lenguaje Sql con MySQL avanzado Parte II. Programas almacenados
Ejemplos:
Pgina 51
Lenguaje Sql con MySQL avanzado Parte II. Programas almacenados
Bloque 1
Bloque 2
Bloque 3
Pgina 52
Lenguaje Sql con MySQL avanzado Parte II. Programas almacenados
error MySQL 1048 (el primer campo de la tabla no puede ser nulo) y no el 1062 como
consecuencia de la lnea 13.
Bloque 4
Se podra hacer uso de una funcin del tipo err_code( ) que indique el cdigo de error
que se ha producido o una variable que almacenara el cdigo de error y su mensaje. Esta
funcin est incluida en los lenguajes de otros gestores de bases de datos y en otros (p.ej
PHP) pero todava no en MySQL (se espera para la versin 5.2, la especificacin
SQL:2003 si que lo incluye). Tambin se echa en falta por el momento (aparecer en la
versin 5.2) la posibilidad de que el usuario provoque intencionadamente situaciones de
error (sentencias del tipo SIGNAL, RAISE) y poder atenderlas dentro de manejadores
de error propios.
Bloque 5
Aunque la excepcin se produce en el bloque interno (lneas 14 a 16), ser atrapada por
el manejador declarado en un nivel superior (bloque externo):
Pgina 53
Lenguaje Sql con MySQL avanzado Parte II. Programas almacenados
Bloque 6
Procedimiento 46 error8
Pgina 54
Lenguaje Sql con MySQL avanzado Parte II. Programas almacenados
2.8 Funciones
2.8.1 Creacin de funciones. Diccionario de Datos
La sintaxis completa de creacin de funciones es:
Pgina 55
Lenguaje Sql con MySQL avanzado Parte II. Programas almacenados
La ventaja que presentan las funciones es que pueden ser utilizadas dentro de
instrucciones SQL y por tanto aumentan considerablemente las capacidades de este
lenguaje.
La mayora de las opciones de la sintaxis anterior son idnticas a las vistas en el tema de
procedimientos. Adems de ello:
Funcin 1 "funcion1"
Pgina 56
Lenguaje Sql con MySQL avanzado Parte II. Programas almacenados
Funcin 2 "funcion2"
La funcin 2 puede mejorarse dejando un solo RETURN (se ejecutar siempre al ser la
ltima instruccin de la funcin) y controlando que los dos nicos parmetros que se le
pasen son 1 o 2 (si no es as la funcin devolver NULL):
Pgina 57
Lenguaje Sql con MySQL avanzado Parte II. Programas almacenados
Funcin 3 "funcion3"
Llamando a la funcin anterior desde dentro de un procedimiento:
Procedimiento 47 f1
Si en lugar del cuerpo de un procedimiento se utiliza una instruccin SELECT para
llamar a la funcin:
Instruccin 3
La anterior sentencia se puede simplificar a partir de la siguiente funcin:
Funcin 4 "funcion4"
Pgina 58
Lenguaje Sql con MySQL avanzado Parte II. Programas almacenados
Instruccin 4
Funcin 5 "funcion5"
Funcin 6 "funcion6"
Funcin 7 "funcion7"
Pgina 59
Lenguaje Sql con MySQL avanzado Parte II. Programas almacenados
2.9 Triggers
2.9.1 Creacin de triggers. Diccionario de Datos
Los triggers, tambin llamados desencadenadores o disparadores, son programas
almacenados que se ejecutan (disparan) automticamente en respuesta a algn suceso
que ocurre en la base de datos. En MySQL ese tipo de suceso se corresponde con alguna
instruccin DML (INSERT, UPDATE, DELETE) sobre alguna tabla.
Pgina 60
Lenguaje Sql con MySQL avanzado Parte II. Programas almacenados
- Nombre del trigger. Sigue las mismas normas que para nombrar cualquier objeto de la
base de datos.
- FOR EACH ROW. Indica que el trigger se ejecutar por cada fila de la tabla afectada
por la operacin DML. Esto es, si tenemos asociado un trigger a la operacin de borrado
de una tabla y se eliminan con una sola instruccin 6 filas de sta ltima, el trigger se
ejecutar 6 veces, una por cada fila eliminada. Otros gestores de bases de datos (as
como futuras implementaciones de MySQL) consideran tambin el otro estndar de
ANSI, la clusula FOR EACH STATEMENT. Con esta segunda opcin, el trigger se
ejecutara por cada operacin DML realizada; en el ejemplo anterior, la instruccin de
borrado dara lugar a que slo se ejecutara el trigger una sola vez en lugar de 6 (filas
afectadas) con esta futura clusula.
Dentro del cuerpo del trigger se puede hacer referencia a los valores de las columnas
que estn siendo modificadas con una sentencia DML (la que provoc que se disparara
el trigger), incluso pueden cambiarse si as se considerara. Para ello se utilizan los
objetos NEW y OLD. De esta manera, en un trigger de tipo BEFORE UPDATE
afectando a una columna micolumna, se utilizar la expresin OLD.micolumna para
conocer el valor de la columna antes de ser modificado y NEW.micolumna ser el nuevo
valor de la columna despus de la modificacin. Estos dos valores slo tienen sentido
los dos juntos en una modificacin, pues ante una insercin (INSERT) no existe valor
antiguo (OLD) y ante un borrado (DELETE) no existe un valor nuevo (NEW) pues el
que existe se elimina. Ver ejemplo trigger1 del apartado 2.9.3.
Pgina 61
Lenguaje Sql con MySQL avanzado Parte II. Programas almacenados
Dentro de un trigger de tipo BEFORE, puede cambiarse el nuevo valor mediante una
sentencia de asignacin SET por lo que anulara por completo el efecto de la instruccin
DML que provoc el trigger.
Eventos de disparo
Pgina 62
Lenguaje Sql con MySQL avanzado Parte II. Programas almacenados
Trigger 1 "trigger1"
Instruccin 5
crea una fila nueva en la tabla alumnos como consecuencia de la instruccin 5 anterior y
otra tambin idntica en la tabla alumnos_replica debido a la ejecucin automtica del
conjunto de instrucciones del trigger.
Otras situaciones en las que se pueden emplear triggers podran ser para llevar el
mantenimiento del stock de artculos: En el momento en que se haga un pedido, se
decrementa automticamente el nmero de unidades pedidas de las existencias de ese
artculo.
Auditora:
Pgina 63
Lenguaje Sql con MySQL avanzado Parte II. Programas almacenados
Trigger 2 trigger 2
la instruccin siguiente:
Instruccin 6
En relacin a este ltimo trigger Qu pasara si el nombre del alumno fuera nulo?
Validacin de datos
- El valor de una columna no debe ser negativo y estar comprendido entre 1 y 80.
- Un empleado que no sea vendedor no puede tener comisin.
- Un empleado no puede ser jefe de si mismo.
-
Siempre que nos encontremos con alguna situacin similar a las anteriores no debemos
dejar que se realice la modificacin de la tabla.
Pgina 64
Lenguaje Sql con MySQL avanzado Parte II. Programas almacenados
cuerpo del trigger se detecta que el dato no es correcto podra provocarse una situacin
de error que anulara y abortara la operacin DML. El problema es que hasta la versin
5.2 por lo menos no aparecer la instruccin SIGNAL (RAISE) que permita provocar
errores como en otros gestores de bases de datos.
No se puede utilizar SQL dinmico para simular una instruccin SIGNAL pues los
triggers no admiten SQL dinmico. Otra estrategia a utilizar en este caso para forzar una
situacin de error y echar atrs el resultado de la sentencia DML que intenta modificar
los datos es realizar una SELECT en el cuerpo del trigger que no recupere ninguna fila.
Al ocurrir un error en el trigger, la combinacin trigger + operacin DML falla y por
tanto aborta la ejecucin de la operacin DML (dem si la combinacin es operacin
DML + trigger).
Supongamos que no se permite altas de alumnos con identificador negativo o cero como
primera columna de la tabla alumnos. Bastar con que codifiquemos un trigger del tipo:
Trigger 3 "trigger3"
Si intentamos realizar primera de las dos siguientes inserciones que vienen a
continuacin, la de una alumna con clave negativa, el trigger fallar y por tanto no se
llevar a cabo la operacin DML que se ejecuta despus (la insercin de la fila) como
puede comprobarse despus de listar la tabla alumnos. En cambio una insercin de un id
superior a 0 har que el trigger finalice correctamente no provocando situacin de error
y por tanto permitiendo despus lanzar la operacin DML de insercin:
Pgina 65
Lenguaje Sql con MySQL avanzado Parte II. Programas almacenados
Por otro lado, tambin puede dar lugar a la aparicin de las siguientes desventajas:
Pgina 66
Lenguaje Sql con MySQL avanzado Parte II. Programas almacenados
2.1 En PHP
El script de este apartado recoge un
nmero de Departamento mediante un
formulario de entrada y manda el dato
(id_centro) al procedimiento almacenado
resulset1 para que este le enve el nmero
de departamento, nombre y presupuesto
de los departamentos. Ej. de ejecucin:
Ilustracin 216 (dcha.). Resultado de llamar al
procedimiento resultset1 desde PHP
Pgina 67
Lenguaje Sql con MySQL avanzado Parte II. Programas almacenados
Pgina 68
Lenguaje Sql con MySQL avanzado Parte II. Programas almacenados
Pgina 69
Lenguaje Sql con MySQL avanzado Parte II. Programas almacenados
3 Ejecucin de funciones
Los dos ejemplos que vienen a continuacin realizan una llamada a la funcin funcion7
vista en el apartado 2.8.2 de este tema (devuelve el nombre de un alumno a partir de un
identificador de alumno que se le pasa como parmetro). Se utilizan sentencias
preparadas tanto en este apartado como en el 2.10.5.
3.1 En PHP
El fragmento de script de este apartado recoge un nmero matrcula de alumno
mediante un formulario de
entrada y enva el dato
(alumno_id) a la funcin
funcion7 para que este
devuelva el nombre. Ej. de
ejecucin
Ilustracin 30. Resultado de llamar a la funcin funcion7 desde PHP
Pgina 70
Lenguaje Sql con MySQL avanzado Parte II. Programas almacenados
4.1 En PHP
Nota: En el siguiente apartado 5.1 tambin se utilizan instrucciones DDL dentro del
script PHP.
Pgina 71
Lenguaje Sql con MySQL avanzado Parte II. Programas almacenados
Ilustracin 34. Resultado de ejecutar por segunda vez el script PHP de creacin de una tabla
5.1 En PHP
El siguiente script tiene la misma funcionalidad que el procedimiento1 visto en este
tema (apartado 2.5.4) en el que es creaba la tabla alumnos y se rellenaba con 5 de ellos.
Pgina 72
Lenguaje Sql con MySQL avanzado Parte II. Programas almacenados
Pgina 73
Lenguaje Sql con MySQL avanzado Parte II. Programas almacenados
Pgina 74
Lenguaje Sql con MySQL avanzado Parte III. Transacciones
PARTE III.
TRANSACCIONES
3.1 Introduccin...........................................................................................2
3.2 Niveles de aislamiento...........................................................................3
3.3 Instrucciones de manejo de transacciones .............................................9
3.4 Transacciones y bloqueos....................................................................13
3.4.1 Deadlock. Cursores de actualizacin..............................15
3.5 Estrategias de bloqueo .........................................................................19
3.6 Aspectos a tener en cuenta a la hora de utilizar transacciones ............21
1. Desde PHP.............................................................................................21
2. Desde Visual Basic Express 2005 .........................................................22
Pgina 1
Lenguaje Sql con MySQL avanzado Parte III. Transacciones
TEMA 3.
Transacciones en MySQL
Alberto Carrera Martn
3.1 Introduccin
TRANSACCIN en SQL: Conjunto de instrucciones SQL, agrupadas lgicamente,
que o bien se ejecutan todas sobre la base de datos o bien no se ejecuta ninguna.
Una transferencia bancaria entre dos cuentas supone un ejemplo claro para ilustrar el
concepto de transaccin. La transferencia se compone de dos operaciones
(instrucciones):
1) Descontar de la libreta origen a transferir la cantidad fijada.
2) Aumentar el saldo de la libreta destino con el importe de la cantidad transferida
de la cuenta origen.
Est claro que la transaccin bancaria anterior no se puede quedar a medias. O bien se
aplican las dos operaciones lgicas que componen la transaccin o bien no se realiza
ninguna por mantener una consistencia contable. Si slo llegara a realizarse una
operacin de las dos anteriores, esta se deshara.
Las transacciones sobre la base de datos deben ajustarse al principio ACID (ATOMIC +
CONSISTENT + ISOLATED + DURABLE), lo que implica que una transaccin debe
ser:
Pgina 2
Lenguaje Sql con MySQL avanzado Parte III. Transacciones
Cada vez que abrimos el programa cliente MySQL Query Browser estamos abriendo
una sesin (podemos tener varias instancias de este programa abiertas varias
sesiones). Para averiguar el identificador de conexin que nos asigna el servidor,
consultaremos la funcin que nos lo proporciona:
Pgina 3
Lenguaje Sql con MySQL avanzado Parte III. Transacciones
Tambin en alguna ocasin hemos creado alguna sesin para trabajar con la base de
datos desde la ventana de lnea de comandos de Windows:
Cada sesin trabaja en su propia zona de memoria pudiendo llegar incluso a bloquear
los datos de la base de datos con los que trabaja.
Los niveles de aislamiento determinan la manera en que las transacciones de una sesin
pueden afectar a los datos recuperados o accedidos por otra sesin. Hay por tanto dos
conceptos interrelacionados: por una lado la concurrencia (varios sesiones realizando
transacciones al mismo tiempo) y por otro el grado de consistencia de los datos.
Determinan tambin el grado en que las transacciones se ajustan al principio ACID.
Cuanto mayor es el grado de aislamiento, menor es el nmero de transacciones que se
pueden realizar concurrentemente pero tambin es menor la posibilidad de que
interfieran las transacciones. Por otro lado, cuanto menor es el grado de aislamiento,
mayor es el nmero de transacciones que se pueden realizar concurrentemente pero el
riesgo de conflicto entre transacciones es elevado.
Pgina 4
Lenguaje Sql con MySQL avanzado Parte III. Transacciones
Nota: Recordar que se mantiene siempre la consistencia en lectura Los datos que ven
las transacciones son los ltimos que se validaron.
Pgina 5
Lenguaje Sql con MySQL avanzado Parte III. Transacciones
En este momento tendrs 3 sesiones abiertas, una del programa MySQL Query Browser
y dos clientes de lnea de comando de MySQL (ilustracin 5). Puedes comprobar el
identificador de cada sesin con la funcin vista anteriormente (SELECT
CONNECTION_ID();):
Como los nmeros de identificacin de conexin sern distintos a los que utilices,
llamaremos A a la conexin de cliente de lnea de comando de identificador ms bajo y
B a la otra conexin de cliente cuyo identificador es ms alto.
Dejaremos la propiedad autocommit a 0 en las dos sesiones abiertas por lo que los
cambios en la base de datos no se almacenan despus de cada instruccin sino cuando
se confirman explcitamente con la instruccin COMMIT.
A
> SET autocommit = 0;
> USE TEST
B
> SET autocommit = 0;
> USE TEST
A
> INSERT INTO alumnos VALUES (6, 'alumno6');
> SELECT * FROM alumnos WHERE id=6;
+----+---------+
| id | alumno |
+----+---------+
| 6 | alumno6 |
+----+---------+
B
> SELECT * FROM alumnos WHERE id=6;
Empty set (0.00 sec)
A
> COMMIT;
B
> SELECT * FROM alumnos WHERE id=6;
Empty set (0.00 sec)
> COMMIT;
Query OK, 0 rows affected (0.00 sec)
> SELECT * FROM alumnos WHERE id=6;
+----+---------+
| id | alumno |
+----+---------+
| 6 | alumno6 |
+----+---------+
1 row in set (0.00 sec)
Pgina 6
Lenguaje Sql con MySQL avanzado Parte III. Transacciones
A
> UPDATE alumnos SET alumno = 'Alberto Carrera' WHERE id=1;
Query OK, 1 row affected (0.01 sec)
Rows matched: 1 Changed: 1 Warnings: 0
> SELECT * FROM ALUMNOS WHERE id=1;
+----+-----------------+
| id | alumno |
+----+-----------------+
| 1 | Alberto Carrera |
+----+-----------------+
1 row in set (0.00 sec)
B
> SELECT * FROM ALUMNOS WHERE id=1;
+----+----------+
| id | alumno |
+----+----------+
| 1 | alumno 1 |
+----+----------+
1 row in set (0.00 sec)
A
mysql> SELECT * FROM ALUMNOS WHERE id=2;
+----+----------+
| id | alumno |
+----+----------+
| 2 | alumno 2 |
+----+----------+
1 row in set (0.00 sec)
mysql> COMMIT;
Query OK, 0 rows affected (0.01 sec)
Pgina 7
Lenguaje Sql con MySQL avanzado Parte III. Transacciones
B
mysql> SELECT * FROM ALUMNOS;
+----+----------------+
| id | alumno |
+----+----------------+
| 1 | alumno 1 |
| 2 | Raquel Carrera |
| 3 | alumno 3 |
| 4 | alumno 4 |
| 5 | alumno 5 |
| 6 | alumno6 |
+----+----------------+
6 rows in set (0.00 sec)
mysql> COMMIT;
Query OK, 0 rows affected (0.02 sec)
mysql> COMMIT;
Query OK, 0 rows affected (0.00 sec)
Pgina 8
Lenguaje Sql con MySQL avanzado Parte III. Transacciones
Pgina 9
Lenguaje Sql con MySQL avanzado Parte III. Transacciones
SET autocommit=0
Nota: Independientemente del valor de la propiedad anterior, todas las sentencias DDL
del lenguaje: ALTER, CREATE, DROP tienen el COMMIT o confirmacin de
manera implcita o automtica.
Procedimiento 1 transac1
La llamada al procedimiento:
En cambio:
Pgina 10
Lenguaje Sql con MySQL avanzado Parte III. Transacciones
Procedimiento 2 transac2
mysql> USE TEST
Database changed
mysql> call transac2(7, 'Blanca Bailin', @n_error, @texto_error);
Query OK, 0 rows affected (0.00 sec)
Pgina 11
Lenguaje Sql con MySQL avanzado Parte III. Transacciones
Procedimiento 3 transac3
CALL transac3 (30, 'Centro 30', 'Los Olivos - Huesca', 140, 'Departamento 140', 40000)
Pgina 12
Lenguaje Sql con MySQL avanzado Parte III. Transacciones
Pgina 13
Lenguaje Sql con MySQL avanzado Parte III. Transacciones
Por otro lado la solucin anterior no es buena para garantizar la clave nica en una
tabla. Imagina que cada departamento se obtiene sumando 10 al nmero ltimo
asignado. Si utilizamos la clusula LOCK IN SHARE MODE puede ocurrir que dos
transacciones lean al mismo tiempo el ltimo id asignado, le sumen 10 y a la hora de
modificarlo provoquen una situacin de clave duplicada o como se ve ms adelante
una situacin de abrazo mortal (deadlock). La solucin para este caso:
Pgina 14
Lenguaje Sql con MySQL avanzado Parte III. Transacciones
Como consecuencia del abrazo mortal anterior, una de las dos transacciones realizar un
ROLLBACK provocando una situacin de error.
Abrimos 2 sesiones A y B:
A
mysql> USE TEST;
Database changed
mysql> SET autocommit = 0;
B
mysql> USE TEST;
Database changed
mysql> SET autocommit = 0;
A
mysql> UPDATE ALUMNOS SET alumno='Alberto Carrera' WHERE id=1;
/* A ya puede ver el cambio producido pero B seguir viendo alumno1
como nombre en lugar de Alberto Carrera */
Pgina 15
Lenguaje Sql con MySQL avanzado Parte III. Transacciones
A
mysql>UPDATE ALUMNOS SET alumno='Carmen Bailin' WHERE id=2;
B
Si ejecutamos rpidamente:
mysql>UPDATE ALUMNOS SET alumno='Raquel Carrera' WHERE id=1;
B
Sigue viendo la pantalla anterior ltima (ilustracin 14).
mysql>COMMIT;
Para probar el cuarto ejemplo hay que lanzar antes otra vez el procedimiento
procedimiento1 para crear de nuevo la tabla alumnos.
Pgina 16
Lenguaje Sql con MySQL avanzado Parte III. Transacciones
Procedimiento 4transac4
A
USE TEST;
SET autocommit = 0;
B
USE TEST;
SET autocommit = 0;
A
UPDATE alumnos SET alumno= 'Mario Carrera'
WHERE id=1;
B
CALL transac4 (1, 'Carmen Bailin', @p_n_error, @p_text_error);
/* Despus de un tiempo de espera 50 segundos en el que parece que se ha quedado
colgado el programa */
Query OK, 0 rows affected (51.55 sec)
SELECT @p_n_error, @p_text_error;
+------------+---------------------------+
| @p_n_error | @p_text_error |
+------------+---------------------------+
| 1205 | Tiempo de espera excedido |
+------------+---------------------------+
Pgina 17
Lenguaje Sql con MySQL avanzado Parte III. Transacciones
Procedimiento 5 transac5
Antes se finalizar este apartado sealar que, como hemos comprobado al intentar
escribir en una fila bloqueada (sin ser deadlock), se ha producido un tiempo de espera
de 50 segundos tras el que se ha producido un error de tiempo de espera excedido
(1205) y la transaccin se ha deshecho.
Pgina 18
Lenguaje Sql con MySQL avanzado Parte III. Transacciones
Posibles soluciones:
Pgina 19
Lenguaje Sql con MySQL avanzado Parte III. Transacciones
Procedimiento 6 transac6
Es una estrategia muy segura pues asegura la consistencia entre la lectura (SELECT) y
la operacin DML (UPDATE), pero limita mucho el rendimiento del sistema al obligar
a las transacciones a largas esperas para poder completarse.
En la estrategia optimista, como la transaccin no bloquea la fila que lee, antes de que
realice la modificacin sobre la misma debe asegurarse que el valor de la fila no ha
cambiado desde que la ley; en caso de que no se hubieran producido cambios se
realizar y confirmar la transaccin, en caso contrario no se llevar a cabo.
Para la eleccin de una estrategia u otra hay que tener en cuenta la concurrencia y
robustez: la estrategia pesimista supone menos errores y reintentos mientras que con la
optimista se reduce el tiempo de duracin de los bloqueos aumentando por tanto la
concurrencia y el rendimiento del sistema.
Generalmente suele utilizarse la estrategia pesimista y slo se recurre a la optimista si la
duracin de los bloqueos o el nmero de filas que se bloquean es elevado en la
estrategia pesimista. De todas formas el uso de una u otra depende mucho de las
caractersticas de la aplicacin.
Pgina 20
Lenguaje Sql con MySQL avanzado Parte III. Transacciones
- La duracin de los bloqueos debe ser lo mnimo posible. De igual manera debe
ser tambin mnimo el nmero de filas a bloquear por las transacciones.
1 Desde PHP
En el siguiente ejemplo se intenta llevar a cabo una transaccin consistente en cambiar
el nombre del alumno de matrcula 1. Si todo va bien aparecer el mensaje Filas
Pgina 21
Lenguaje Sql con MySQL avanzado Parte III. Transacciones
'..................
Dim MiConexion As New MySqlConnection(cadena_conexion)
Dim cadena_sql As String = "UPDATE alumnos" + _
" SET alumno='Mario Carrera' " + _
" WHERE id=1"
Dim instruccion As MySqlCommand = New MySqlCommand(cadena_sql, MiConexion)
MiConexion.Open()
Dim MiTransaccion As MySqlTransaction = MiConexion.BeginTransaction
Try
Dim filas_afectadas As Integer
filas_afectadas = instruccion.ExecuteNonQuery()
Console.WriteLine("Filas afectadas: " + filas_afectadas.ToString)
MiTransaccion.Commit()
Console.WriteLine("Transaccin finalizada")
Catch Exception As MySqlException
Console.WriteLine("Error en la transaccin: ")
Console.WriteLine(Exception.Message)
Try
MiTransaccion.Rollback()
Console.WriteLine("Transaction no realizada")
Catch RollbackException As MySqlException
Console.WriteLine("Rollback fallido:")
Console.WriteLine(RollbackException.Message)
End Try
End Try
'..................
Pgina 22
Lenguaje SQL con MySQL avanzado Parte IV. Optimizacin
PARTE IV.
OPTIMIZACIN DE MySQL.
4.1 Introduccin.......................................................................................... 2
4.2 Los ndices............................................................................................ 4
4.2.1 ndices parciales ... 4
4.2.2 ndices multicolumna (ndices compuestos) 5
4.2.3 ndices full-text 5
4.2.4 Los ndices y el operador LIKE .. 7
4.2.5 Los ndices y la cardinalidad 8
4.3 Rendimiento y optimizacin de las consultas ... 8
4.3.1 Detectar las consultas lentas. Activar el slow query log .. 8
4.3.2 Optimizacin de consultas mediante la sentencia EXPLAIN .. 9
4.3.3 Ejemplos del uso de la sentencia EXPLAIN . 13
4.3.4 Comando ANALYZE TABLE .. 16
4.3.5 Comando OPTIMIZE TABLE 18
4.4 Gestin de la memoria en el servidor MySQL 20
4.4.1 Ajustar las propiedades de memoria de los threads que
genera MySQL 20
4.4.2 Utilizacin siempre que sea posible de las tablas tipo MEMORY
4.4.3 Descripcin y uso de la Query Cach de MySQL 21
4.4.4 Descripcin y uso de la Cach de claves (Key Cache) de
MySQL . 24
4.4.5 Mejoras en los join, sort, y escaneo completo de tablas 25
4.5 Herramientas relacionadas con el rendimiento................................... 28
4.5.1 Optimizacin de expresiones y funciones mediante la funcin
BENCHMARK() 28
4.5.2 Test de rendimiento (Benchmarking) . 29
Pgina 1
Lenguaje SQL con MySQL avanzado Parte IV. Optimizacin
TEMA 4.
Optimizacin de MySQL.
Javier Robles Cascallar
4.1 Introduccin.
Para poder seguir este tema es necesario partir de unos conocimientos bsicos en la
arquitectura de MySQL y en tareas de administracin. En concreto al lector se le supone
familiarizado en los siguientes aspectos:
Muchos de los ejemplos de este documento se han creado usando la base de datos llamada
curso cuya descripcin de las tablas libros, bibliotecas, ejemplares,
codigospostales es la siguiente:
+-------------+------------------+------+-----+---------+---------+
| Field | Type | Null | Key | Default | Extra |
+-------------+------------------+------+-----+---------+---------+
| id | int(10) unsigned | NO | PRI | NULL | auto_inc|
| TITULO | varchar(200) | YES | | NULL | |
| AUTOR | varchar(100) | YES | | NULL | |
| COMENTARIOS | varchar(100) | YES | | NULL | |
| NUMPAGINAS | int(5) | YES | | NULL | |
+-------------+------------------+------+-----+---------+---------+
5 rows in set (0.00 sec)
Pgina 2
Lenguaje SQL con MySQL avanzado Parte IV. Optimizacin
Pgina 3
Lenguaje SQL con MySQL avanzado Parte IV. Optimizacin
4. 2 ndices.
Los ndices, como ya es bien conocido, permiten al servidor de base de datos localizar
rpidamente, en las consultas, los registros buscados sin tener que hacer un recorrido
completo de la tabla para su recuperacin. Los administradores, ante el hecho de crear un
ndice sobre un atributo de una tabla, siempre deben analizar si el aumento de la velocidad
en las respuestas a las consultas que afectan a esa tabla compensa el espacio en disco
requerido para almacenar el ndice y tambin la posible sobrecarga del procesador a la hora
de actualizar el ndice cuando se realizan modificaciones sobre los datos de la tabla.
En este apartado no nos vamos a detener, por lo tanto, en como se crean, se modifican, o se
eliminan ndices en MySQL pues esos conocimientos ya se suponen adquiridos. Lo que se
pretende es dar a conocer al lector determinados aspectos no tan conocidos sobre los ndices
y tambin posibles estrategias de indexacin.
4. 2. 1 ndices parciales.
En ocasiones es ms conveniente generar un ndice no sobre un atributo completo de una
tabla sino sobre una parte de ese atributo. La principal ventaja de esta medida es el ahorro
de espacio a la hora de almacenar dicho ndice.
Supongamos, por ejemplo, que tenemos una base de datos de libros donde se almacena el
catlogo de una biblioteca . En esa base de datos hay una columna de una tabla donde se
guarda el ttulo del libro. Si hacemos un ndice sobre esa columna ttulo sabiendo que la
longitud media de un ttulo son unos 30 bytes y que nuestro catlogo tiene unos cien mil
registros implica que el ndice puede ocupar unos 3Gbytes (probablemente no ocupara
tanto porque MySQL incorpora algoritmos de compresin para reducir el tamao de los
ndices).
Si en lugar de crear un ndice por todo el titulo lo creamos por los seis primeros caracteres
mediante un ndice parcial podemos hacer que el tamao final del ndice se reduzca en una
quinta parte.
El inconveniente de los ndices parciales es que retornan a veces ms filas de las deseadas
que luego la consulta debe descartar porque no coinciden con lo que se esta buscando. Si
seguimos con el ejemplo anterior la siguiente consulta:
Hace que el ndice retorne todos los ttulos que comiencen por la cas como la casa
de los espritus o la casqueria fina, filas que posteriormente la consulta debe
descartar.
Cuando queremos crear un ndice para una columna tipo TEXT o BLOB, en ese caso, es
necesario que el ndice sea de tipo parcial. Por ejemplo:
Pgina 4
Lenguaje SQL con MySQL avanzado Parte IV. Optimizacin
Para no hacer el ndice muy grande se indexan nicamente los seis primeros bytes de cada
atributo.
Tambin es muy importante para este tipo de ndices el orden en que se colocan los
atributos. En el caso del ejemplo una consulta del tipo:
Requiere hacer un escaneo completo de la tabla puesto que todas las entradas del ndice se
inician con apellido y solo a continuacin de dicha entrada se incluye el contenido de
nombre.
Vamos a ver con un ejemplo la diferencia de realizar una bsqueda de una palabra en un
texto largo primero sin tener definido un ndice full-text y posteriormente con un ndice
full-text aadido a la tabla.
En nuestra base de datos curso tenemos la tabla aforismos donde se han recopilado frases
celebres de distintos personajes. La tabla tiene cien mil registros creados con la utilidad
Datagen (ver Anexo 1. Uso de la herramienta DataGen para insertar mltiples filas en
Pgina 5
Lenguaje SQL con MySQL avanzado Parte IV. Optimizacin
tablas de prueba), evidentemente hay un montn de frases repetidas pero para el ejemplo
no es relevante, y tiene la siguiente estructura:
CREATE TABLE `aforismos` (
`id` int(10) unsigned NOT NULL auto_increment,
`fecha` date default NULL,
`cuerpo_carta` varchar(350) default NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM
Se desea localizar cuantos aforismos incluyen la palabra Unamuno como se supone que
no tenemos aun un ndice full-text definido sobre el atributo tenemos que usar el operador
LIKE
Para usar un ndice full-text es necesario utilizar la funcin MATCH (campo) AGAINST
(palabras). En el ejemplo la consulta ser:
Pgina 6
Lenguaje SQL con MySQL avanzado Parte IV. Optimizacin
Por el contrario la siguiente consulta no puede hacer uso del ndice y requiere escanear por
completo la tabla:
A partir de la versin MySQL 5 las consultas del tipo LIKE %cadena%, siempre que
cadena sea mayor de 3 caracteres, son resueltas mediante el algoritmo Turbo Boyer-Moore,
lo que permite incrementar la velocidad de respuesta en este tipo de consultas.
Pgina 7
Lenguaje SQL con MySQL avanzado Parte IV. Optimizacin
Una vez activado, y segn el ejemplo anterior, todas las consultas que superen los 5
segundos de tiempo de respuesta van a quedar registradas en el fichero mysql-slow.log y
por lo tanto fcilmente detectadas por el administrador.
El problema con este log es que si hay mucho trfico en el servidor es probable que tambin
haya muchas consultas consideradas lentas, entonces el log crece rpidamente y se hace
difcil extraer de l informacin til. Lo ms importante es extraer del log las consultas
lentas con mayor nmero de ocurrencias y tambin las consultas con ms tiempo de
procesamiento para proceder a su optimizacin (siempre que sea posible).
Hay un script de Perl que viene con la distribucin de MySQL que se llama mysqldumpslow
y que puede ser muy til para extraer informacin del slow query log cuando este ha crecido
y ha alcanzado un tamao considerable. Por ejemplo si queremos que mysqldumpslow
Pgina 8
Lenguaje SQL con MySQL avanzado Parte IV. Optimizacin
extraiga del fichero log ordenado por nmero de ocurrencias las cinco consultas lentas que
ms veces aparecen en el fichero slow query log debemos lanzar el siguiente comando
desde la consola:
C:\wamp\mysql\scripts>perl mysqldumpslow -t 1 C:\wamp\logs\mysql-slow.log
Nota: Conviene observar que este ejemplo se esta realizando en un servidor MySQL bajo Windows por lo
que necesita tener instalado un interprete de Perl para Windows (ver Anexo 2 de este documento: Instalar
interprete de Perl para Windows ActivePerl).
El primer ejemplo del uso de Explain lo vamos a ver usando una consulta muy rpida sobre
la tabla libros de la base de datos curso para obtener informacin de un registro concreto
conocido el valor de su clave primaria:
MySQL sabe antes de ejecutar la consulta anterior que solo puede haber un registro de
salida a lo sumo, si es que existe ese valor de la clave primaria. La informacin que genera
Explain sobre esta consulta es la siguiente:
Pgina 9
Lenguaje SQL con MySQL avanzado Parte IV. Optimizacin
index. Cuando sobre una tabla hay un ndice asociado y MySQL detecta que
es capaz de responder la consulta nicamente a partir de la informacin del
propio ndice sin necesidad de recuperar datos de la tabla asociada al ndice.
Por ejemplo si suponemos que a la tabla libros se le ha aadido el siguiente
ndice:
mysql> ALTER TABLE libros ADD INDEX (titulo);
MySQL es ahora capaz de responder a la siguiente consulta solo accediendo
al ndice recin creado:
select titulo from libros
where UPPER(titulo) like'%QUIJOTE%';
La principal ventaja de este tipo de bsqueda es que el ndice es ms
pequeo que la tabla. Si la consulta se modifica aadiendo columnas que ya
no estn en el ndice MySQL esta obligado a leer la tabla completa y el type
pasara a ALL.
select titulo,autor from libros
where UPPER(titulo) like'%QUIJOTE%';
Pgina 10
Lenguaje SQL con MySQL avanzado Parte IV. Optimizacin
where cod_pos='300001';
Si la sentencia Explain retorna ref_or_null es porque tambin se estn
buscando registros asociados a los valores nulos del ndice. Por ejemplo:
select poblacion from codigospostales
where cod_pos='300001' or cod_pos is null;
eq_ref. Este tipo de busqueda indica que hay un join establecido y que la
tabla marcada como eq_ref por la sentencia Explain avisa que est usando
una clave primaria o ndice tipo unique para resolver la consulta de forma
mucho ms rpida. Por ejemplo si queremos saber los ttulos de las
bibliotecas que tienen como nombre Universidad Carlos III necesitamos
hacer un join de las tres tablas de esta forma.
select titulo from ejemplares e,bibliotecas b,libros l
where upper(nombre) like '%UNIVERSIDAD CARLOS III%' AND
e.id_bib=b.id and e.id_tit=l.id
Si se observa la salida generada por Explain para esta sentencia se ve que se
generan tres registros uno por cada tabla implicada:
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: b
type: ALL
possible_keys: PRIMARY
key: NULL
key_len: NULL
ref: NULL
rows: 70
Extra:
*************************** 2. row ***************************
id: 1
select_type: SIMPLE
table: e
type: ref
possible_keys: fk_ejemplares1,fk_ejemplares2
key: fk_ejemplares2
key_len: 5
ref: curso.b.id
rows: 425
Extra: Using where
*************************** 3. row ***************************
id: 1
select_type: SIMPLE
table: l
type: eq_ref
possible_keys: PRIMARY
key: PRIMARY
key_len: 4
ref: curso.e.id_tit
rows: 1
Extra: Using where
El primer registro marca el type para la tabla bibliotecas como ALL, es
decir debe leer toda la tabla bibliotecas para obtener los registros.
El segundo registro marca el type para la tabla ejemplares como ref
porque utiliza para el join, como referencia, la clave ajena que apunta a la
tabla bibliotecas. Ese ndice no es un ndice nico para la tabla ejemplares
puesto que esta repetido en muchos registros.
Pgina 11
Lenguaje SQL con MySQL avanzado Parte IV. Optimizacin
Pgina 12
Lenguaje SQL con MySQL avanzado Parte IV. Optimizacin
mysql> select titulo from libros where id between 6321 and 6327;
+-----------------------------------+
| titulo |
+-----------------------------------+
| Psicologia social |
| Anatomia general |
| Viajes por Marruecos |
| Los siete pilares de la sabiduria |
| La Ilustracion en Espaa |
| Delphi 3.0 |
+-----------------------------------+
6 rows in set (0.25 sec)
Podemos observar la diferencia entre buscar en un rango o buscar un valor nico. El campo
type pasa de valer de const a range, lo que indica que esta buscando no un nico valor
sino un rango de ellos. Tambin se observa que el campo rows vale 7, aunque la consulta
devuelve 6 filas. Esto se debe a que el campo rows es obtenido a partir de una estimacin
de las filas que puede generar esa consulta. Lo que hace MySQL es estimar cuantas filas en
una clave autonumrica puede haber entre los valores 6327 y 6321 y el resultado es 7
aunque su valor real almacenado sea 6 puesto que el registro con la clave 6325 no aparece
en la tabla.
Ejemplo 2. El siguiente ejemplo va a ser realizar una consulta buscando valores de una
columna que no tiene ndice asociado.
mysql> select count(*) from libros where numpaginas>700;
+----------+
| count(*) |
+----------+
| 3738 |
+----------+
1 row in set (0.41 sec)
Pgina 13
Lenguaje SQL con MySQL avanzado Parte IV. Optimizacin
Se observa que el valor NULL en el campo key indica que no est utilizando ningn ndice
para resolver la cnsulta y el campo posible_keys ndica que no existe ningn ndice
posible para resolverla. Tambin conviene fijarse que el campo type indica ALL, es decir, el
rango de bsqueda de posibles valores se extiende a toda la tabla.
Pgina 14
Lenguaje SQL con MySQL avanzado Parte IV. Optimizacin
Ejemplo 3. Vamos a ver otro ejemplo de Explain en el que se va a efectuar una consulta
basada en dos columnas indexadas. MySQL buscar seleccionar de los dos posibles ndices
aquel que menos filas tenga que examinar.
mysql> select count(*) from libros where numpaginas >998 and id <
6000;
+----------+
| count(*) |
+----------+
| 5 |
+----------+
1 row in set (0.03 sec)
Se observa que en este caso MySQL ha optado entre PRIMARY y NUMPAGINAS por
NUMPAGINAS porque ha detectado que el valor 998 est casi en uno de los extremos
superiores del ndice y van a ser muy pocas filas las que necesite examinar.
Si cambiamos el valor de 998 por el de 220 vemos que MySQL opta por cambiar el ndice
elegido para la consulta porque detecta que prcticamente todas las filas de la tabla tienen
un valor superior a 220 en la columna NUMPAGINAS.
mysql> select count(*) from libros where numpaginas >220 and id <
6000;
+----------+
| count(*) |
+----------+
| 5857 |
+----------+
1 row in set (0.02 sec)
Pgina 15
Lenguaje SQL con MySQL avanzado Parte IV. Optimizacin
ref: NULL
rows: 5044
Extra: Using where
1 row in set (0.00 sec)
Es aconsejable ejecutar este comando peridicamente sobre todo para tablas que tienen
frecuentes modificaciones en sus datos que afectan a las columnas indexadas.
Mediante el uso del comando SHOW INDEX podemos observar los cambios en la informacin
relativa a los ndices que genera el comando ANALYZE TABLE.
Veamos el siguiente ejemplo sobre una tabla concreta libros que tiene dos ndices
asociados, su clave primaria y numpaginas.
Pgina 16
Lenguaje SQL con MySQL avanzado Parte IV. Optimizacin
Volvemos a lanzar de nuevo el comando SHOW INDEX para observar como ha cambiado la
informacin relativa a los ndices. El cambio afecta fundamentalmente al atributo
Cardinality, que se refiere al nmero estimado de valores distintos en el ndice (ojo con
la palabra estimado, porque no tiene por qu coincidir con el valor real en un momento
dado).
mysql> show index from libros \G
*************************** 1. row ***************************
Table: libros
Non_unique: 0
Key_name: PRIMARY
Seq_in_index: 1
Column_name: id
Collation: A
Cardinality: 10182
Sub_part: NULL
Packed: NULL
Null:
Index_type: BTREE
Comment:
*************************** 2. row ***************************
Table: libros
Pgina 17
Lenguaje SQL con MySQL avanzado Parte IV. Optimizacin
Non_unique: 1
Key_name: NUMPAGINAS
Seq_in_index: 1
Column_name: NUMPAGINAS
Collation: A
Cardinality: 1697
Sub_part: NULL
Packed: NULL
Null: YES
Index_type: BTREE
Comment:
2 rows in set (0.37 sec)
Este comando debe ser usado cuando se han eliminado gran parte de las filas de una tabla o
se han efectuado numerosas modificaciones en tablas con columnas tipo VARCHAR, BLOB o
TEXT. Podemos decir que este comando equivale a desfragmentar el espacio de datos de una
tabla. Solo funciona en tablas del tipo MyISAM, BDB e InnoDB.
OPTIMIZE TABLE tambin bloquea la tabla durante su ejecucin, como hace ANALYZE
TABLE, la diferencia es que OPTIMIZE TABLE es mucho ms lento puesto que tiene que
reallocar los datos de la tabla para hacer la desfragmentacin por lo tanto es importante
saber cuando se va a lanzar el proceso de optimizacin. Lo habitual seria una vez a la
semana o al mes y solo para ciertas tablas.
Veamos un ejemplo guiado paso a paso para ver los efectos de usar el comando OPTIMIZE
TABLE.
2. Insertamos valores aleatorios en las columnas campo2 y campo3 hasta tener unos 100.000
registros en la tabla. (Se ha usado la utilidad Datagen para insertar mltiples filas en una
tabla. Para ver el uso de la utilidad Datagen consultar el Apndice 1: Uso de la
herramienta DataGen para insertar mltiples filas en tablas de prueba).
Pgina 18
Lenguaje SQL con MySQL avanzado Parte IV. Optimizacin
Avg_row_length: 39
Data_length: 3928312
Max_data_length: 281474976710655
Index_length: 1029120
Data_free: 0
Auto_increment: 110001
Create_time: 2006-06-15 13:21:16
Update_time: 2006-06-15 13:25:56
Check_time: NULL
Collation: latin1_swedish_ci
Checksum: NULL
Create_options:
Comment:
1 row in set (0.00 sec)
Donde se observa que el tamao total no ha variado ni tampoco el tamao del ndice
Rows: 100000
Avg_row_length: 42
Data_length: 4224160
Max_data_length: 281474976710655
Index_length: 1286144
Data_free: 0
8. Optimizamos la tabla
mysql>optimize table ejemplo_optimize;
9. Para finalizar observamos que los datos una vez optimizada son los siguientes:
Rows: 100000
Avg_row_length: 39
Data_length: 3927044
Max_data_length: 281474976710655
Index_length: 1022976
Data_free: 0
Ha disminuido el tamao total ocupado por los datos y el tamao ocupado por el ndice.
Pgina 19
Lenguaje SQL con MySQL avanzado Parte IV. Optimizacin
Para observar el nmero de trheads que est generando nuestro servidor MySQL
lo vemos fcilmente mediante SHOW STATUS.
mysql> show status like '%thread%';
+------------------------+-------+
| Variable_name | Value |
+------------------------+-------+
| Delayed_insert_threads | 0 |
| Slow_launch_threads | 0 |
| Threads_cached | 10 |
| Threads_connected | 2 |
| Threads_created | 14 |
| Threads_running | 1 |
+------------------------+-------+
En este ejemplo se ve que el servidor ha creado catorce threads, aunque solo hay dos
threads conectados y por lo tanto quedan diez esperando en cach.
Pgina 20
Lenguaje SQL con MySQL avanzado Parte IV. Optimizacin
Es importante entender las diferencias existentes entre los cuatro mecanismos de cach que
administra el servidor MySQL:
Buffer pool. Este cach almacena datos e ndices de aquellas tablas con arquitectura
de almacenamiento InnoDB.
Key cache. Este tipo de cach se utiliza para almacenar informacin de los ndices
de las tablas tipo MyISAM.
Memory pool. Este cach lo utiliza MySQL fundamentalmente para almacenar
informacin del diccionario de datos. Solo se benefician de este tipo de cach las
tablas tipo InnoDB.
Query cache. Este tipo de cach almacena consultas y resultados de consulta
realizada sobre cualquier tabla independientemente de la arquitectura de
almacenamiento de la misma.
Tambin es importante saber que tipo de sucesos obligan a actualizar los datos de la query
cache:
Pgina 21
Lenguaje SQL con MySQL avanzado Parte IV. Optimizacin
Modificaciones en los datos o en las estructuras de tablas y/o ndices. En tablas con
alta carga transaccional esto sucede constantemente. Adems no solo se refrescan
las posibles filas afectadas por las modificaciones, es necesario refrescar todas las
filas de la query cache que hacen referencia a la tabla modificada, incluso las
posibles filas que no han sido modificadas.
Teniendo en cuenta los puntos anteriores se evidencia que activar la Query cache es tanto
ms efectivo desde el punto de vista del rendimiento cuanto ms estables son las tablas
afectadas por las consultas.
Para activar la query cache basta con reservar un espacio de memoria para alojarla. Esto se
hace dando un valor a la variable query_cache size, bien usando el comando SET
GLOBAL o mejor desde el fichero de configuracin my.cnf (o my.ini en Windows).
query_cache_size=8M
Esta opcin es la habitual y la que viene por defecto en la configuracin del servidor
MySQL. Es la ms adecuada en bases de datos con ms tablas estticas que
dinmicas.
query_cache_type=2/DEMAND. Significa que el acceso a la query cache debe ser
explcito para que se produzca, es decir, solo se beneficiarn del uso de la query
cache las sentencias que lleven la opcin SQL_CACHE.
Esta opcin es la adecuada en bases de datos con un elevado nmero de tablas muy
dinmicas sobre las que se hacen frecuentes consultas.
Pgina 22
Lenguaje SQL con MySQL avanzado Parte IV. Optimizacin
Se observa como ha descendido el ratio de hits sobre el total de las consultas que han
pasado por la query cache al tiempo que ha aumentado considerablemente el nmero de
consultas eliminadas por falta de espacio. Quiz el administrador en esta situacin debera
plantearse la necesidad de asignar ms espacio a la query cache al tiempo que debera tratar
de determinar que consultas, probablemente, no se van a beneficiar de la query cache para
aadir la opcin SQL_NO_CACHE en sus sentencias SELECT.
Pgina 23
Lenguaje SQL con MySQL avanzado Parte IV. Optimizacin
Existe la posibilidad de crear varias cachs de claves distintas en lugar de la nica cach de
claves por defecto que configura MySQL. Se puede crear, por ejemplo, una cach de claves
para soportar los ndices de las tablas con elevada carga transaccional y alto contenido
dinmico y otro cach de claves distinto para las tablas ms estticas. Separar las cachs de
claves significa que distintos usuarios o aplicaciones no se interferirn con otros en el uso
concurrente del espacio de cach.
MySQL usa la cach de claves como todo mecanismo de cach. Cuando necesita acceder a
un bloque de ndice lo intenta localizar en la cach de claves antes de acceder a disco. Si lo
localiza lo lee, o escribe sobre l, dependiendo de la operacin que fuera a realizar. Si no lo
encuentra el servidor escoge un bloque de la cach conteniendo ndices de otra tabla y los
sustituye copiando sobre ellos los bloques de ndice de la tabla que ha tenido que cargar del
disco. Tan pronto como el bloque de ndice est en la cach de claves los datos de los
ndices ya pueden ser accedidos. La estrategia que utiliza MySQL para sustituir los bloques
es la llamada por sus siglas LRU (Last Recently Used), es decir mantiene una estructura de
lista en la que entra por la cola el ltimo bloque accedido, de tal manera que cuando
necesita sustituir un bloque siempre selecciona el que indica la cabeza de la lista.
Los bloques de ndices pueden ser modificados dentro de la cach de claves. Cuando un
bloque es modificado ya no se permite el acceso concurrente a ese bloque. El resto de
usuarios que necesiten usar ese bloque deben esperar hasta que el bloque modificado sea
escrito en disco.
Pgina 24
Lenguaje SQL con MySQL avanzado Parte IV. Optimizacin
La sentencia CACHE INDEX es la que permite asignar los ndices de distintas tablas a
distintas cachs de claves. Se van a asignar tres tablas de la base de datos curso a la cach
que hemos nombrado como hot_cache en el ejemplo:
+----------------+--------------------+----------+----------+
| Table | Op | Msg_type | Msg_text |
+----------------+--------------------+----------+----------+
| curso.clientes | assign_to_keycache | status | OK |
| curso.reservas | assign_to_keycache | status | OK |
| curso.viajes | assign_to_keycache | status | OK |
+----------------+--------------------+----------+----------+
3 rows in set (0.01 sec)
Si se hace la asociacin de las tablas con las distintas cachs lanzando el comando CACHE
INDEX desde la consola lo que sucede es que, si reinicia el servidor, se pierde esta
asociacin. Lo ideal para que la asociacin se mantenga es crear un script de sql (llamado
por ejemplo mis_caches.sql) donde se incluyen las sentencias CACHE INDEX anteriores.
Script mis_caches.sql
CACHE INDEX curso.clientes,curso.reservas,curso.viajes IN hot_cache;
CACHE INDEX bd2.tabla1,bd2.tabla2 IN cold_cache;
Lo que se hace es incluir en el fichero de opciones my.ini la opcin init_file que permite
cargar el script anterior al arrancar el servidor.
.
key_buffer_size=6M
hot_cache.key_buffer_size = 2M
cold_cache.key_buffer_size = 2M
init_file=/path_a_la_carpeta_del_script/mis_caches.sql
Pgina 25
Lenguaje SQL con MySQL avanzado Parte IV. Optimizacin
2. A esta tabla le insertamos, para poder realizar el ejemplo, cinco millones de registros.
(Ver el apndice Uso de la herramienta DataGen para insertar mltiples filas en tablas de
prueba ).
3. Creamos una nueva tabla llamada pruebasort2 con estructura de datos idntica a
pruebasort.
5. Es interesante ver ahora las variables de status que afectan a la ordenacin para analizar
como se ha realizado el algoritmo de sort.
Pgina 26
Lenguaje SQL con MySQL avanzado Parte IV. Optimizacin
Lo que llama la atencin es que se han necesitado 498 procesos merge para completar el
sort (es una cifra considerablemente alta). Cuando esta cifra es elevada es cuando el
administrador debe considerar el incrementar la variable sort_buffer_size.
10. Por ltimo, un vistazo a las variables de estatus para ver como se ha realizado el sort:
Pgina 27
Lenguaje SQL con MySQL avanzado Parte IV. Optimizacin
BENCHMARK(num_veces,expresin_funcion);
El uso de esta funcin se ve muy bien con un ejemplo sencillo. Vamos a calcular el tiempo
empleado en usar cien veces la funcin SYSDATE().
mysql> select benchmark(100,sysdate());
+--------------------------+
| benchmark(100,sysdate()) |
+--------------------------+
| 0 |
+--------------------------+
1 row in set (0.00 sec)
Se observa un tiempo despreciable. Ahora se llama cien mil veces a la misma funcin.
Genera un tiempo de 2,60 segundos. En este caso se aprecia con SYSDATE() que
incrementando el nmero de veces que se ejecuta aumenta el tiempo de ejecucin de forma
lineal.
La funcin BENCHMARK() puede ser muy til para encontrar problemas o cuellos de botella
en consultas que se ejecutan muchas veces y tienen expresiones complejas en su interior. Es
aconsejable ejecutar BENCHMARK() algunas veces a distintas horas del da e interpretar el
resultado en el sentido del nivel de carga que tiene la mquina del servidor.
Pgina 28
Lenguaje SQL con MySQL avanzado Parte IV. Optimizacin
Los test de prueba estn localizados en una carpeta de nombre bench ( o sql-bench) que se
encuentra bajo la carpeta de instalacin de MySQL y son los siguientes:
compare-results
copy-db
crash-me
print-limit-table
run-all-tests
server-cfg
test-alter-table
test-ATIS
test-big-tables
test-connect
test-create
test-insert
test-select
test-wisconsin
Ejecutar todos ellos en bloque supone lanzar el script run-all-tests, siempre teniendo muy
en cuenta que el tiempo de lanzar todos los test en bloque puede ser bastante elevado (entre
hora y 1 hora dependiendo del procesador).
Veamos un ejemplo de ejecucin del test que mide el rendimiento de consultas sobre tablas
(test-select). Desde la consola de comandos nos situamos en la carpeta donde se encuentran
los test:
Pgina 29
Lenguaje SQL con MySQL avanzado Parte IV. Optimizacin
Creating table
Inserting 10000 rows
Time to insert (10000): 377 wallclock secs ( 0.93 usr 0.31 sys + 0.00
cusr 0.00 csys = 1.24 CPU)
Time for select_cache2 (10000): 90 wallclock secs ( 1.43 usr 0.28 sys +
0.00 cusr 0.00 csys = 1.71 CPU)
Es interesante observar las acciones que ha ido realizando el test y el tiempo medido en
pulsos de reloj del sistema que ha empleado para cada una de las acciones, adems de
establecer, al final, el tiempo total empleado. Un dato que destaca es el tiempo empleado en
crear la tabla e insertar las 10000 filas (377 wallclock secs), esto se debe a que el fichero de
configuracin my.ini, en el caso del ejemplo, tiene como opcin por defecto crear las tablas
en arquitectura InnoDB, donde las inserciones son muchsimo ms lentas que las tablas tipo
MyISAM debido fundamentalmente a las verificaciones de integridad referencial que
Pgina 30
Lenguaje SQL con MySQL avanzado Parte IV. Optimizacin
necesitan hacer las tablas InnoDB y que las tablas MyISAM ignoran. Es muy importante
conocer el tipo de tablas por defecto que genera nuestro servidor de base de datos antes de
lanzar los test de rendimiento.
Un test un poco especial es el llamado crash-me que consiste en probar todos las
caractersticas, capacidades y lmites del sistema de base de datos. Cuando se lance este test
es conveniente que el ordenador no est realizando ningn otro tipo de actividad. La salida
generada por crash-me es bastante extensa como para visualizarla desde consola, conviene
lanzar el test con la opcin config-file=n_fichero que permite almacenar la
informacin generada.
No se va a visualizar en este documento toda la salida generada por el test crash-me porque
es muy extensa, pero si, por ejemplo, podemos ver en un extracto, una vez editado el
fichero del ejemplo test01-09-2006.txt, como el test ha calculado que el tamao
mximo de un dato tipo varchar es de 1048543 bytes de longitud.
.
max_varchar_size=1048543 # max varchar() size
###We are trying (example with N=5):
###create table crash_q (q varchar(5))
###insert into crash_q values ('aaaaa')
###select * from crash_q
### 524287:OK 786431:OK 917503:OK 983039:OK 1015807:OK 1032191:OK
1040383:OK 1044479:OK 1046527:OK 1047551:OK 1048063:OK 1048319:OK
1048447:OK 1048511:OK 1048543:OK 1048559:FAIL 1048546:FAIL 1048544:FAIL
.
Para poder ver todas las opciones posibles a la hora de lanzar un test concreto usamos la
opcion --help.
Pgina 31
Lenguaje SQL con MySQL avanzado Parte IV. Optimizacin
Pgina 32
Lenguaje SQL con MySQL avanzado Parte IV. Optimizacin
Al finalizar los pasos de este asistente ya tenemos un conector ODBC para MySQL
instalado. Lo podemos comprobar si abrimos el listado de conectores ODBC que tiene
nuestro sistema operativo siguiendo la secuencia de mens:
Paso 2. Crear una conexin ODBC a una base de datos concreta de nuestro servidor
MySQL.
Para crear una conexin ODBC que permita conectar cualquier programa cliente con la
base de datos curso de mi servidor de base de datos MySQL se debe realizar lo siguiente:
Pgina 33
Lenguaje SQL con MySQL avanzado Parte IV. Optimizacin
Se lanza desde MySQL la siguiente sentencia que nos crear la tabla necesaria para el
ejemplo.
Pgina 34
Lenguaje SQL con MySQL avanzado Parte IV. Optimizacin
Nota: La tabla puede ser tanto MyISAM como InnoDB. DataGen funciona muchsimo ms
rpido si la tabla es MyISAM, al eliminar todas las verificaciones de integridad.
Una vez creada la estructura de la tabla ejecutamos el programa DataGen. Lo primero que
tenemos que hacer es indicarle al programa que debemos utilizar la conexin ODBC creada
en el paso 2. Pulsamos el botn para que aparezca la ventana que permite
seleccionar el vnculo de datos.
Al pulsar Siguiente la siguiente ventana nos lista los nombres de los DSN de usuario de
los origenes de datos ODBC. Debemos seleccionar el creado en el paso 2 con el nombre
mi_conexion_mysql. Antes de pulsar Aceptar probamos la conexin con el botn Probar
Conexin.
Pgina 35
Lenguaje SQL con MySQL avanzado Parte IV. Optimizacin
Debemos decirle a la aplicacin cmo rellenamos cada una de las columnas de la tabla.
Existen diversas posibilidades y vamos a ver como se han aplicado en nuestro ejemplo.
Tal como muestra la siguiente ventana el campo clave [Integer], al estar definido como de
tipo auto_increment, va a ser el propio servidor MySQL el encargado de introducir sus
valores, por lo tanto DataGen no va a ocuparse de esta columna y dejamos desmarcada la
opcin Use Datasource asociada a este campo.
Pgina 36
Lenguaje SQL con MySQL avanzado Parte IV. Optimizacin
Pgina 37
Lenguaje SQL con MySQL avanzado Parte IV. Optimizacin
El campo fecha [dbdate] tal como se ve a continuacin se va a rellenar con valores tipo
fecha generados aleatoriamente.
Por ltimo el campo valor [integer] se va a rellenar seleccionando valores de una columna
tambin de tipo entero pero de la tabla libros que se encuentra en la misma base de datos
curso, en concreto es la columna numpaginas.
Pgina 38
Lenguaje SQL con MySQL avanzado Parte IV. Optimizacin
Una vez definidos como se van a rellenar las columnas de la tabla fijamos el nmero de
filas que deseamos (en nuestro ejemplo 5000) y pulsamos el botn Go!.
Type 'help;' or '\h' for help. Type '\c' to clear the buffer.
mysql>
Pgina 39
Lenguaje SQL con MySQL avanzado Parte IV. Optimizacin
Desde el men Inicio ejecutamos el programa Perl Package Manager (PPM). PPM es un
gestor de paquetes similar a los gestores de paquetes .rpm o .deb del entorno linux.
Tenemos que comprobar que aparecen dentro de la lista de paquetes, como paquetes
instalados, los dos siguientes:
- DBI
- DBD-mysql
En el caso de que no estuviera alguno de los dos instalados es necesario visualizar todos
los paquetes disponibles [Ctrl 1], localizar en el listado el paquete concreto, por ejemplo
DBD-mysql, marcarlo para su instalacin pulsando la tecla [+] y por ltimo proceder a
Pgina 40
Lenguaje SQL con MySQL avanzado Parte IV. Optimizacin
Pgina 41
Lenguaje SQL con MySQL avanzado Parte IV. Optimizacin
El administrador de MySQL est diseado para trabajar a partir de la versin 4.0 o superior.
Entre las tareas que MySQL Administrator puede realizar se incluyen:
Instalacin en Windows
Pgina 42
Lenguaje SQL con MySQL avanzado Parte IV. Optimizacin
Instalacin en Linux.
El archivo de tar.qz genrico permite que se instale las herramientass de GUI de MySQL
en la mayora de las distribuciones de Linux. El archivo a bajar se llama mysql-gui-tools-
versio-.linux-i386.tar.gz, donde versin indica la versin del producto (por ejemplo, 5.0r4).
Para instalar las herramientas de GUI de MySQL se lanza desde la shell el siguiente
comando:
En el que hay especificar los datos del servidor, nombre de usuario, contrasea y puerto de
la base de datos a la cual se desea conectar. Una vez introducidos de forma correcta,
aparece la pantalla principal del programa donde se visualiza por defecto la informacin
ms relevante sobre el servidor de MySQL y el cliente que ha establecido la conexin:
Pgina 43
Lenguaje SQL con MySQL avanzado Parte IV. Optimizacin
Pgina 44
Lenguaje SQL con MySQL avanzado Parte IV. Optimizacin
que en este caso solo podemos arrancar servidores de datos en el mismo host
donde esta ejecutndose MySQL Administrador.
Muchas de las opciones de configuracin de la base de datos son muy sencillas de entender
y de utilizar, por lo menos todas las opciones ms bsicas. En conjunto con MySQL Query
Browse, nos permite gestionar cualquier aspecto de una base de datos MySQL.
Este documento no trata de dar una visin exhaustiva de MySQL Administrador solo
pretende destacar con un poco ms de detalle un par tareas que posiblemente son de las que
MySQL Administrador puede ayudar ms a los usuarios que realizan labores de
administracin. Dichas tareas se centran en:
- Administracin de usuarios.
- Como generar grficos a medida para monitorizar la evolucin de las
variables de sistema (system variables) y el estado del sistema (status
variables).
Pgina 45
Lenguaje SQL con MySQL avanzado Parte IV. Optimizacin
Entre las distintas opciones de MySQL Administrator tenemos una seccin para la gestin
de usuarios, sus permisos, host de acceso, etc. La podemos ver y seleccionar en la barra de
opciones de la izquierda.
Inicialmente solo hay un usuario creado, en muchas de las configuraciones tpicas, que es el
usuario root. La lista de usuarios creados aparece en la parte de abajo de la barra de la
izquierda. Podemos seleccionar cualquier usuario para editar sus propiedades.
- User information: con los datos de login (nombre de usuario y contrasea de acceso) y
otros datos personales del usuario, que es opcional completar.
Pgina 46
Lenguaje SQL con MySQL avanzado Parte IV. Optimizacin
- Schema Privileges: con los permisos asociados a ese usuario en las distintas bases de datos
de MySQL.
- Resources: con los recursos disponibles para ese usuario.
Si queremos crear un usuario podemos pulsar el botn de New User y aparecer la ventana
de propiedades del usuario, en la pestaa de User Information, para que introduzcamos el
nombre para este usuario y la contrasea que vamos a asignar.
Podemos entrar en otras pestaas para terminar de introducir los datos del usuario. La
pestaa de Schema Privileges es especialmente interesante, ya que nos permite seleccionar
los permisos de este usuario para cada base de datos de nuestro sistema.
La ventana de Schema Privileges nos permite seleccionar una base de datos y entonces
accedemos a una lista con todos los privilegios posibles para permitir o denegar.
Inicialmente, para un usuario nuevo, todos los permisos estn denegados, as que tendremos
que seleccionar los que deseamos otorgar. Para ello simplemente seleccionamos entre los
avaliable privileges (permisos disponibles) y los pasamos a assigned privileges (permisos
asignados). En la siguiente imagen se observa como el usuario pedro tiene sobre la base de
datos concesionario asignados determinados privilegios (la mayor parte) y an tiene unos
cuantos disponibles que el administrador ha decidido no asignarle por el momento. El
usuario pedro podr realizar tareas de administracin si previamente el usuario root le ha
concedido todos los derechos sobre la base de datos mysql del servidor.
Pgina 47
Lenguaje SQL con MySQL avanzado Parte IV. Optimizacin
Vamos a ver como con MySQL Administrador podemos controlar los host desde los que se
pueden conectar los distintos usuarios.
Inicialmente cualquier usuario creado se puede conectar desde cualquier host o computador
posible. Para
Si esta situacin no nos conviene, podemos definir nuevos host pulsando con el botn
derecho del ratn sobre el usuario al que queremos aadir ordenadores de acceso. Entonces
nos sale un formulario para indicar el nombre del host que queremos aadir a ese usuario, o
su direccin IP.
En cualquier momento, si hacemos doble clic sobre un usuario y nos sale debajo una lista
de hosts, es que ese usuario se puede conectar desde cualquier de esos hosts y adems,
podremos asignar permisos distintos al usuario cuando se conecte desde cada ordenador
posible. De modo que un usuario si se conecta, por ejemplo desde localhost, puede tener
ms permisos que si se conecta desde otros ordenadores de la red local o de Internet.
En la imagen anterior se entiende que el usuario pedro se puede conectar desde localhost (el
ordenador local) y desde otro equipo llamado con la direccin IP 192.168.1.101. Pero es
muy importante tener cuidado con esta lista de hosts, porque a lo mejor todava estamos
permitiendo que el usuario prueba se pueda conectar desde cualquier host y es posible que
no deseemos que eso se permita, sino que solo se deje acceder si se accede desde esos host
especificados.
Para darnos cuenta de este detalle podemos ver en la ventana de propiedades del usuario el
nombre del usuario que sale, para saber los hosts que estn permitidos.
Pgina 48
Lenguaje SQL con MySQL avanzado Parte IV. Optimizacin
Usuario Pedro
desde
192.168.1.101
En esta imagen nos hemos situado en el host 192.168.1.101 del usuario pedro. Vemos que
en la parte de arriba, en la parte de propiedades del usuario aparece pedro@192.168.1.101.
Eso quiere decir que est definido el usuario pedro siempre que se conecte desde
192.168.1.101 y que estamos en la ventana de propiedades de ese usuario.
Pgina 49
Lenguaje SQL con MySQL avanzado Parte IV. Optimizacin
Usuario Pedro
desde cualquier
host
Nos hemos situado encima del usuario pedro. Si nos fijamos en la parte de arriba de las
propiedades del usuario veremos como aparece "pedro", donde en la imagen anterior
apareca pedro@192.168.1.101. Por lo tanto en esta situacin el usuario pedro, como no
est acompaado de ningn nombre de host, significa que puede accederse desde cualquier
equipo.
Si queremos evitar que el usuario pedro pueda acceder desde cualquier equipo,
simplemente pulsamos con el botn derecho en el nombre de usuario y seleccionamos la
opcin que pone "Remove Host From Which The User Can Connect". Entonces, si hemos
pulsado sobre el nombre del usuario nos quitar el acceso del usuario desde cualquier host.
Si hacemos la misma accin sobre cualquier nombre de host, como localhost, nos quitar la
posibilidad de que el usuario se pueda conectar desde ese ordenador.
Pgina 50
Lenguaje SQL con MySQL avanzado Parte IV. Optimizacin
Usuario Pedro
desde
192.168.1.101
Apretando con el botn derecho en cualquier usuario o host nos dar una serie de opciones
para el mantenimiento de ese usuario o host que no hemos nombrado, como aadir un
usuario, borrarlo o duplicarlo.
Pgina 51
Lenguaje SQL con MySQL avanzado Parte IV. Optimizacin
En la configuracin por defecto aparecen dos pestaas con una serie de grficos
predefinidos. La pestaa Connectin Health muestra informacin sobre las conexiones de
los usuarios y el trfico y la pestaa Memory Health que indica el uso de la Query Cache y
de la Key Cache como muestra la siguiente imagen:
En concreto el grfico Query Cache Hitrate es un buen indicador del uso de la Query Cache
de MySQL.
Para ver como se han creado estos grficos predefinidos de MySQL Administrator basta
con poner el ratn sobre el grafico y con el botn derecho seleccionamos la opcin Edit
Graph del men contextual. Aparece una ventana que permite editar los parmetros de
configuracin del grfico tales como la formula empleada para dibujar la grafica, el tipo de
unidad de medida, el valor mnimo y mximo a alcanzar, etc. La formula se basa en una
expresin sobre los valores recogidos en la variables de estado de MySQL o bien en el
valor relativo de estos respecto a la ltima lectura dependiendo de lo especificado en la
expresin [variable] o ^[variable] :
Pgina 52
Lenguaje SQL con MySQL avanzado Parte IV. Optimizacin
El grafico, por lo tanto, responde a la formula recogida en la caja de texto Value Formula.
Pgina 53
Lenguaje SQL con MySQL avanzado Parte IV. Optimizacin
El primer paso consiste en crear una nueva pgina o pestaa en la seccin Health. Para ello
basta con pulsar el botn derecho del ratn en el men contextual y seleccionar la opcin
Add a Page.
Ponemos como ttulo o Page Caption Sentencias SQL y a continuacin como Page
Description:
Como segundo paso es necesario crear algn grupo. Todos los grficos estn organizados
en torno a grupos. Seleccionamos la opcin Add a Group y creamos dos grupos tal como
aparece en esta imagen:
Pgina 54
Lenguaje SQL con MySQL avanzado Parte IV. Optimizacin
Como ltimo paso y ubicando el ratn dentro de cada grupo seleccionamos Add a Graph
para aadir los dos grficos. La ventana del primer grfico la rellenamos con los valores
que se ven en esta imagen:
Pgina 55
Lenguaje SQL con MySQL avanzado Parte IV. Optimizacin
Para el segundo grafico que contabiliza las sentencias de actualizacin la formula ser la
siguiente:
Finalmente una vez creados ambos grficos deberamos visualizar algo parecido a esta
ventana:
Pgina 56