Transacciones y bloqueos en Sql Server

En muchas situaciones, la modificación de datos requiere varios pasos. Por 
ejemplo, puede necesitar cambiar los valores en dos tablas separadas. 

Puede usar transacciones para completar estas dos operaciones como una unidad, o si ocurre un error, no cambia ninguna de las tablas. Otra consideración clave es que la mayoría de las bases de datos deben ser compatibles con muchas operaciones simultáneamente. Tiene varias opciones para configurar cómo se bloquean los datos mientras el usuario los modifica. En la primera parte de la serie de artículos Transaction and Locking, aprenderá los fundamentos acerca de las transacciones de SQL Server, cómo funcionan y cómo administrarlas, y cómo escribir procedimientos que usan transacciones.

Fundamentos de transacción

Una transacción es una serie de sentencias y procedimientos de comandos SQL 
que se ejecutan como una única unidad lógica. Una transacción exitosa debe 
exhibir las siguientes cuatro propiedades:

  • Atomicidad: la transacción es una sola unidad de trabajo en la que se completan todos los pasos o no.
  • Consistencia: la transacción debe dejar todos los datos en un estado consistente.
  • Aislamiento: loscambios realizados por las transacciones simultáneas deben estar aislados entre sí, lo que significa que ninguna transacción debe encontrar datos en un estado indeterminado (en el proceso de cambio).
  • Durabilidad: los cambios realizados por la transacción se mantienen.

SQL Server confirma (escribe permanentemente) las instrucciones de una 
transacción en la base de datos solo después de que todas se ejecutan correctamente. Este es un ejemplo de la propiedad de atomicidad. La atomicidad es crítica cuando todas o ninguna de las manipulaciones deben completarse juntas. Si las declaraciones en una transacción fallan, el desarrollador deshace toda la transacción. Cuando 
se retrotrae una transacción, SQL Server no confirma ninguna declaración en la base de datos. 
Usted impone la coherencia a través de objetos de base de datos tales como:

  • Restricciones de teclas principales
  • Restricciones de clave externa
  • Verificar restricciones
  • Disparadores

SQL Server es responsable de la coherencia interna, como asegurarse de que las estructuras internas de datos no estén dañadas. Usted impone el aislamiento a través de la configuración de aislamiento de transacción. Puede controlar qué tan estricto se aplica el aislamiento, si se permite o no el acceso a los datos mientras se aplica una transacción, y el alcance del aislamiento. El alcance del aislamiento varía de una sola fila a una base de datos completa.

Usted aplica la durabilidad cuando realiza una transacción. SQL Server usa el registro de transacciones para garantizar la durabilidad al mantener una copia de la transacción hasta que se aplique físicamente a los objetos de la base de datos.

Cómo funcionan las transacciones

El siguiente es un ejemplo de cómo funcionan las transacciones. Tienes dos tablas: Savings to Checking. Cuando transfiere dinero de Savings to Checking, deben ocurrir dos acciones:

  • El monto debe deducirse de la columna Saldo en Ahorros.
  • El importe debe agregarse a la columna Saldo en Comprobación.

Si solo ocurre una de estas acciones, los datos son inconsistentes. Puede garantizar la coherencia de los datos mediante el uso de transacciones.

Rol de registro de transacciones

El registro de transacciones hace posible la transacción ACID.

  • Las transacciones se escriben en el registro de transacciones.
  • En caso de que se produzca una falla del sistema o después de la recuperación de las copias de seguridad, SQL Server procesa el contenido del registro de transacciones para llevar las tablas e índices de la base de datos a un estado constante hasta el punto de falla.
  • Las transacciones completadas y confirmadas se aplican (avanzando).
  • Las transacciones incompletas o no confirmadas se retrotraen.

Modos de transacción

SQL Server admite los siguientes modos de transacción:

  • Explícito: elextracto debe comenzar, comprometerse y retrotraerse explícitamente en cada transacción.
  • Implícito: lapróxima transacción comienza automáticamente cuando la transacción anterior se confirma o se retrotrae.
  • Autocommit: Cada declaración es su propia transacción.
  • Ámbito del lote:todas las transacciones que se inician en una sesión de múltiples conjuntos de resultados activos (MARS) forman parte de una transacción con alcance por lotes y cualquier transacción que no se complete cuando el lote se complete se revierte.
  • Gestiona transacciones por separado para cada conexión. Puede configurar un modo de transacción diferente para cada conexión según sea necesario. A menos que se especifique lo contrario, SQL Server opera en modo de confirmación automática con cada instrucción tratada como una transacción independiente.

Conjuntos de resultados activos múltiples (MARS)

Las versiones anteriores de SQL Server no permitían múltiples declaraciones activas en una sola conexión. Las aplicaciones tenían que procesar o cancelar los conjuntos de resultados de un lote antes de ejecutar un mismo lote en la misma conexión. Esto satisfizo las necesidades de la mayoría de las aplicaciones, pero no todas.

SQL Server 2005 presentó compatibilidad para múltiples conjuntos de resultados activos (MARS) en aplicaciones que acceden al Motor de base de datos. Esto significa que una aplicación puede mantener múltiples conjuntos de resultados, conocidos como conjuntos de resultados activos múltiples (MARS) en una sola conexión. MARS opera intercalando solicitudes y no procesando solicitudes en paralelo. El soporte de MARS está deshabilitado por defecto. 

Para obtener más información sobre MARS, consulte Uso de Múltiples conjuntos de resultados activos (MARS)

Estados de cuenta

Usted gestiona las transacciones agrupando un conjunto de declaraciones. Agrupe 
las declaraciones definiendo el comienzo, el final y entre estos, los puntos de guardado 
y los puntos de retroceso para las transacciones explícitas. SQL Server admite las 
siguientes declaraciones para implementar transacciones:

  • BEGIN TRANSACTION:identifica el comienzo de una transacción. Después de que se abre, una transacción permanece abierta hasta que se confirma o se retrotrae.
  • COMPROMISO DE TRANSACCIÓN:identifica el final de una transacción. La instrucción informa a SQL Server que tiene todas las declaraciones necesarias para completar la transacción.
  • GUARDAR TRANSACCIÓN:coloca un punto de rescate en la transacción como un lugar seguro donde la transacción puede revertirse. Puede hacer referencia al nombre en una Instrucción ROLLBACK TRANSACTION .
  • ROLLBACK TRANSACTION:transfiere una transacción al último punto de rescate o un punto de rescate especificado por nombre. Si no se ha establecido un punto de rescate, la transacción retrocede al comienzo de la transacción. Si la transacción ya está comprometida, no puede deshacerse.

La función @@TRANCOUNT devuelve el número de transacciones abiertas para una conexión. Cada vez que se inicia una transacción , SQL Server incrementa @@TRANCOUNT en 1. Cada vez que una transacción se compromete, SQL Server reduce @@ TRANCOUNT en 1. Si una transacción se retrotrae al principio (no a un punto de rescate), SQL Server establece @ @TRANCOUNT a 0. Usualmente usa @@ TRANCOUNT cuando necesita anidar transacciones. Una transacción anidada es una transacción definida dentro de los límites de otra transacción. Para obtener más información , consulte Transacciones anidadas
La instrucción BEGIN TRANSACTION

La sintaxis para la instrucción BEGIN TRANSACTION es:

BEGIN TRAN[SACTION] [transaction_name | @tran_name_var

[WITH MARK [‘description‘]]]

  

Puede usar el valor transaction_name o @tran_name_var (variable de nombre de transacción ) para asignar un identificador a la transacción. El nombre de la transacción es obligatorio si usa la cláusula WITH MARK. Cuando define una transacción usando WITH MARK, la descripción se ingresa en el registro de transacciones. Puede usar marcas de transacción durante la restauración de la base de datos para restaurar hasta el punto de una transacción específica.

La declaración COMMIT TRANSACTION

La sintaxis de la instrucción COMMIT TRANSACTION es:

 

COMMIT [TRAN [SACTION]] [ transaction_name | @ tran_name_var ]]

 

Si ejecuta COMMIT TRAN cuando @@ TRANCOUNT es igual a cero, SQL 
Server genera un error porque no hay un TREN DE COMIENZO correspondiente.

Alternativamente, puede ejecutar transacciones de confirmación con:

COMMIT [WORK]

COMMIT especificado por sí mismo con la palabra clave WORK es compatible con SQL-92.

La declaración SAVE TRANSACTION

Utiliza la instrucción SAVE TRANSACTION para establecer puntos de rescate en una transacción que permite retrocesos parciales. SQL Server no libera recursos de transacción hasta que la transacción completa se confirma o se retrotrae.

La sintaxis para SAVE TRANSACTION es:

 

SAVE TRAN[SACTION] savepoint_name | @savepoint_name_var

Debe usar un identificador válido para el nombre del punto de guardado. SQL Server no admite puntos de guardado para transacciones distribuidas. Una transacción distribuida es aquella que involucra acciones en múltiples servidores.

La instrucción ROLLBACK TRANSACTION

La instrucción ROLLBACK TRANSACTION transfiere una transacción al comienzo de la transacción o a un punto de rescate establecido dentro de la transacción. Cuando revierte una transacción, todos los cambios se borran en el punto de rescate definido (si existe) o al comienzo de la transacción. La sintaxis para este comando es:

ROLLBACK TRAN[SACTION] [transaction_name | @tran_name_var

| savepoint_name | @savepoint_name_var]

 

Si usa ROLLBACK TRAN en un desencadenador, todas las instrucciones en el desencadenador que siguen a la reversión aún se ejecutan. Sin embargo, una vez que finaliza el desencadenador, finaliza el lote que llamó al enunciado que provocó el disparo del desencadenador. ROLLBACK TRAN funciona de manera diferente si ocurre dentro de un procedimiento almacenado. Las instrucciones en el lote que llamó al procedimiento almacenado aún se ejecutan. La versión compatible con SQL-92 de este comando es:

 

ROLLBACK [WORK]

ROLLBACK WORK es esencialmente lo mismo que ROLLBACK TRAN, excepto que los 
nombres de las transacciones y los nombres de los puntos de rescate no son compatibles.

Ejemplo de transacción

Como ejemplo, tiene dos procedimientos almacenados que deben completarse con atomicidad. Este ejemplo asume que ya ha definido dos procedimientos almacenados llamados rev_inv y rev_cust que se usan para actualizar las tablas de la base de datos y que la transacción se usa dentro de un procedimiento almacenado que define las variables @paid, @invdate e @invnum. Para definir esto como una transacción, ejecuta:

 

    BEGIN TRAN cust_pay

EXEC rev_inv @paid, @invnum

EXEC rev_cust @paid, @invdate

COMMIT TRAN

 

Para modificar el ejemplo para utilizar la comprobación de errores estructurados, ejecute lo 
siguiente:

BEGIN TRAN cust_pay

BEGIN TRY

EXEC rev_inv @payed, @invnum

EXEC rev_cust @payed, @invdate

COMMIT TRAN

END TRY

BEGIN CATCH

print “An error occurred”

ROLLBACK TRAN

END CATCH

   

Usted tiene cierto control sobre cómo SQL Server reacciona a los errores. De forma predeterminada, si se produce un error de instrucción en tiempo de ejecución durante el procesamiento por lotes; solo la declaración que causó el error se revierte automáticamente por el motor de la base de datos . Usted controla este comportamiento utilizando la opción XACT_ABORT , que está establecida en OFF por defecto. La sintaxis de esta opción es:

 

SET XACT_ABORT ON | OFF

   

Cuando establece la opción XACT_ABORT en ON y se produce un error de tiempo de ejecución, el motor de la base de datos retrotrae la transacción actual completa. Sin embargo, en lugar de confiar en reversiones automáticas, debe incluir un 
código de manejo de errores explícito en lotes que ejecutan transacciones.

Transacciones implícitas

Para activar y desactivar el soporte para transacciones implícitas, use lo 
siguiente:

SET IMPLICIT_TRANSACTIONS ON | OFF

Cuando se establece en ON, se iniciará una transacción cuando se ejecuta ALTER TABLE, CREATE, DELETE, DROP, FETCH, GRANT, INSERT, OPEN, REVOKE, SELECT, TRUNCATE TABLE o UPDATE, y una transacción aún no está abierta. Cuando la opción IMPLICIT_TRANSACTION está establecida en ON, debe confirmar o revertir la transacción. De lo contrario, SQL Server revierte los cambios cuando el usuario se desconecta. Cuando tiene la opción IMPLICIT_TRANSACTION establecida en OFF, cada declaración se considera una transacción (modo de confirmación automática).

Declaraciones y consideraciones ilegales

No debe usar ciertas declaraciones en las transacciones definidas por el usuario porque las funciones que realizan no se pueden deshacer. Los rollbacks deben poder deshacer funciones; por lo tanto, debe evitar usar las siguientes declaraciones en una transacción:

  • CREATE TABLE, ALTER TABLE, TRUNCATE TABLE
  • CREATE INDEX
  • All DROP statements
  • SELECT…INTO
  • GRANT or REVOKE
  • DISK INIT, LOAD DATABASE, LOAD TRANSACTION
  • Cualquier usuario o procedimiento almacenado del sistema que utiliza cualquiera de 
    las declaraciones anteriores

En muchos casos, SQL Server no genera un error cuando utiliza estas declaraciones en una transacción. Sin embargo, no deben usarse debido a la naturaleza de las declaraciones. Además, el motor de base de datos genera un error cuando intenta ejecutar cualquiera de las siguientes declaraciones dentro de una transacción:

  • CREATE DATABASE, ALTER DATABASE, DROP DATABASE
  • COPIA DE SEGURIDAD DE RESTAURACION
  • RECONFIGURE
  • UPDATE STATISTICS

 

Visión general de bloqueo

El bloqueo es una parte necesaria del proceso de transacción cuando se trabaja en un 
entorno de procesamiento de transacciones en línea multiusuario (OLTP). SQL Server usa bloqueos para evitar conflictos de actualización. Por ejemplo, cuando un usuario actualiza los datos en la tabla, los bloqueos de SQL Server impiden que otros usuarios accedan a los datos que se están actualizando. Los bloqueos ayudan a prevenir:

  • Lost Updates: ocurre cuando dos transacciones están actualizando los mismos datos simultáneamente. Los cambios se guardan en la última transacción que se escribe en la base de datos, perdiendo cambios de otra transacción.
  • Dirty reads: Se produce cuando una transacción lee datos no confirmados de otra transacción. Esto puede conducir a cambios para realizar cambios inexactos en los datos. Esto también se conoce como una dependencia no comprometida.
  • Nonrepeatable reads: Se produce cuando cambian los datos de fila entre las lecturas de datos. Esto también se conoce como análisis inconsistente.
  • Phantoms: aparece un registro cuando una transacción relee los datos luego de realizar un cambio Puede serializar transaccionescon bloqueos, lo que significa que solo una persona puede cambiar un elemento de datos, como una fila en particular, todo a la vez. SQL Server puede emitir un bloqueo para:
    • Un identificador de fila (RID), que bloquea una sola fila en una tabla.
    • Una clave, que es un bloqueo de fila dentro de un índice
    • Una tabla que bloquea todas las filas e índices de datos
    • Una base de datos, que se utiliza al restaurar una base de datos
    • Una página que bloquea una página de datos o índice de 8 KB
    • Una medida, bloqueo de un grupo contiguo de páginas durante la asignación de espacio.

SQL Server selecciona un nivel de bloqueo apropiado para la manipulación de datos actual o acción de definición. Por ejemplo, SQL Server usa un bloqueo de fila para actualizar una sola fila de datos en una tabla. SQL Server utiliza la gestión de bloqueo dinámico, lo que significa que el nivel de bloqueo se puede ajustar automáticamente según sea necesario. Puede usar la vista de administración dinámica sys.dm_tran_locks para obtener información acerca de los bloqueos activos.

Bloqueos básicos

SQL Server admite los siguientes tipos de bloqueos:

  • Bloqueos compartidos (S): se usa cuando se realizan operaciones de solo lectura en la base de datos. Los recursos bloqueados con un bloqueo compartido están disponibles para SELECT, pero no para modificación.
  • Bloqueos exclusivos (X): se usan para operaciones que modifican datos, como las instrucciones INSERT, UPDATE y DELETE que requieren bloqueos exclusivos. No más de una transacción puede tener un bloqueo exclusivo en un recurso. Si hay un bloqueo exclusivo en un recurso, ninguna otra transacción puede acceder a ese recurso.
  • Bloqueo de intención: establece una jerarquía de bloqueo. Por ejemplo, si una transacción tiene un bloqueo exclusivo en una fila, SQL Server coloca un bloqueo de intención en la tabla. Cuando otra transacción solicita un bloqueo en una fila de la tabla, SQL Server sabe que debe verificar las filas para ver si tienen bloqueos. Si una tabla no tiene un bloqueo de intención, puede emitir el bloqueo solicitado sin verificar cada fila para un bloqueo.
  • Bloqueo de actualización (U): este tipo de bloqueo generalmente se coloca en una página antes de realizar una actualización. Cuando SQL Server está listo para actualizar la página, el bloqueo se promoverá a un bloqueo de página exclusivo.
  • Bloqueo de esquema: se usa para evitar que una tabla o índice que se está utilizando en otra sesión se descarte o se modifique su esquema. Cuando un recurso está bloqueado con un bloqueo de esquema, no se puede acceder al objeto.
  • Bloqueos de actualización masiva (BU): se usa para evitar que otros procesos accedan a una tabla mientras se procesa el procedimiento de carga masiva. Sin embargo, permitirá el tratamiento de procesos concurrentes de carga masiva, lo que le permitirá ejecutar cargas paralelas. Un procedimiento de carga masiva se realiza mediante el uso de un programa de copia masiva (bcp) o BULK INSERT.


Bloqueo optimista y pesimista

Son los dos términos que se usan comúnmente para describir los métodos de bloqueo:

  • El bloqueo pesimista bloquea los recursos a medida que se adquieren, manteniendo bloqueos en la duración de la transacción. Es más probable que cause bloqueos. Un punto muerto se produce cuando dos transacciones bloquean el acceso a los recursos necesarios para la otra transacción.
  • El bloqueo optimista supone que los conflictos entre transacciones no son probables, pero podría suceder. Las transacciones se pueden ejecutar sin bloquear recursos. La única vez que los recursos están controlados por un conflicto es cuando se realizan cambios en los datos. Si se produce un conflicto, la transacción se revierte.

Versión de fila

Desde el lanzamiento de SQL Server 2005, Microsoft introdujo el control de versiones de filas como alternativa a los bloqueos compartidos. Con el control de versiones de filas, las filas se leen en tempdb al comienzo de una transacción, y la transacción utiliza esa copia de esas filas a lo largo de la transacción. El control de versiones de fila protege la 
transacción de:

  • Dirty reads
  • Nonrepeatable reads
  • Phantoms

Incluso cuando se utiliza el control de versiones de filas, SQL Server aún tiene un bloqueo exclusivo en una fila antes de actualizarlo.

El control de versiones de filas permite una concurrencia óptima (múltiples usuarios acceden a los datos al mismo tiempo), a la vez que proporciona una buena protección. Sin embargo, debe asegurarse de que tempdb tenga suficiente espacio en disco disponible. El uso de versiones de fila también puede degradar el rendimiento debido a los recursos necesarios para mover datos dentro y fuera de tempdb.


Aislamiento de transacción

El aislamiento de transacciones protege las actividades de transacciones realizadas fuera de la transacción, cumpliendo con los requisitos de aislamiento de una transacción ACID. Administra el aislamiento de transacciones como una configuración de nivel de sesión que afecta todas las operaciones en sus sesiones. Puede anular el nivel de aislamiento utilizando las cuentas individuales de bloqueo de cuentas.

Para establecer el nivel de aislamiento de la transacción, ejecuta:

    SET TRANSACTION ISOLATION LEVELREAD COMMITTED | READ UNCOMMITTED | REPEATABLE READ | SNAPSHOT | SERIALIZABLE

 

Los niveles de aislamiento se definen de la siguiente manera:

  • READ UNCOMMITED: las lecturas sucias son posibles. No se adquiere un bloqueo compartido y no se respetan los bloqueos exclusivos.
  • READ COMMITED: Evita lecturas sucias mediante el uso de bloqueos compartidos o versiones de filas. El método utilizado depende de la configuración de la opción de base de datos READ_COMMITED_SNAPSHOT. Si está activado, SQL Server utiliza el control de versiones de filas. Si está desactivado, SQL Server usa bloqueos compartidos. El uso del control de versiones de filas mejora la concurrencia porque SQL Server administra el control de versiones de filas en un nivel de instrucción, no repetible, que son causadas por cambios de datos entre lecturas.
  • REPEATABLE READS: No se pueden realizar lecturas sucias y lecturas no repetibles. Los bloqueos de lectura se mantienen hasta que la transacción se confirma o se retrotrae.
  • SNAPSHOT: Los cambios de datos realizados fuera de la transacción después de que comience la transacción no son visibles dentro de la transacción. Utiliza el control de versiones de filas. No se mantienen bloqueos compartidos. Cuando intenta actualizar los datos, SQL Server compara los datos actuales con los almacenados en tempdb. Si son diferentes, la actualización falla y la transacción se retrotrae. Solo se usará si la opción de base de datos está EN ALERTA_SALIDA_ISOLACIÓN .
  • SERIALIZABLE: otras transacciones no pueden actualizar o insertar ninguna nueva fila que haya leído la transacción hasta que se haya confirmado la transacción actual.

Después de cambiar el nivel de aislamiento, puede ejecutar USEROPTIONS DBCC para 
verificar que el cambio se realizó en la conexión actual.

Hints de Tabla

También puede usar sugerencias de tabla para anular el bloqueo utilizado para una sola instrucción SELECT, UPDATE, INSERT o DELETE. Las sugerencias de tabla se especifican en la cláusula FROM de la instrucción DML y afectan solo a la tabla o vista a la que se hace referencia en esa cláusula. La siguiente es la sintaxis general para especificar sugerencias de tabla:

WITH  ( <table_hint> [ [, ]…n ] )

        <table_hint> ::=

        [ NOEXPAND ] {

    INDEX  ( index_value [ ,…n ] )

  | INDEX =  ( index_value )   

  | FORCESEEK [( index_value ( index_column_name  [ ,… ] ) ) ]

  | FORCESCAN

  | FORCESEEK

  | HOLDLOCK

  | NOLOCK

  | NOWAIT

  | PAGLOCK

  | READCOMMITTED

  | READCOMMITTEDLOCK

  | READPAST

  | READUNCOMMITTED

  | REPEATABLEREAD

  | ROWLOCK

  | SERIALIZABLE

  | SPATIAL_WINDOW_MAX_CELLS = integer

  | TABLOCK

  | TABLOCKX

  | UPDLOCK

  | XLOCK

}

<table_hint_limited> ::=

{

    KEEPIDENTITY

  | KEEPDEFAULTS

  | HOLDLOCK

  | IGNORE_CONSTRAINTS

  | IGNORE_TRIGGERS

  | NOLOCK

  | NOWAIT

  | PAGLOCK

  | READCOMMITTED

  | READCOMMITTEDLOCK

  | READPAST

  | REPEATABLEREAD

  | ROWLOCK

  | SERIALIZABLE

  | TABLOCK

  | TABLOCKX

  | UPDLOCK

  | XLOCK

}

 

   

Para obtener más información sobre los consejos de tabla y las sugerencias relacionadas con el bloqueo, consulte Sugerencias de tabla (Transact-SQL).

A Marte voy

Predicados “SARGABLES” 

SARGABLE viene del acrónico SARG (Search ARGument) y se refiere a una clausula WHERE que compara una columna con una constante. ¿Y eso que significa? Pues que un WHERE es SARGABLE cuando se puede apoyar en índices para mejorar la respuesta. Los WHERE NON-SARGABLE, en cambio, son aquellos que no pueden ayudarse de índices a la hora de realizar el filtrado de datos. Hay que evitar los operadores NON-SARGABLE.

Hay algunos operadores que pueden impedir (aunque no siempre) la utilización de índices en un WHERE. Los operadores en cuestión son: “IS NULL”, “<>”, “!=”, “!>”, “!<” (estos dos últimos en caso de que existan para ese motor, ya que no son comunes), “NOT”, “NOT EXIST” , “NOT IN”, “NOT LIKE”. Básicamente todas las que usan NOT)

Además, las expresiones que incluyen una función sobre una columna, comparaciones contra una columna – no es una constante – u operadores con la misma columna en ambos lados, son también NON-SARGABLE.

No obstante, hay veces que hay alguna condición con estos operadores y no significa necesariamente que el WHERE sea NON-SARGABLE, porque otra condición puede hacer que la consulta utilice un índice que evite el TABLE/INDEX SCAN (es lo que ocurre con WHERE NON-SARGABLE) y realice un COVERED INDEX sin necesidad de utilizar el índice. Esto ocurre cuando el índice incluye los campos devueltos por el SELECT y los del JOIN. Por otra parte, un WHERE puede también estar compuesto por otra clausula que tire de otro índice.

De todas formas, no siempre viene bien hacer un COVERED INDEX, ya que cuando los índices son muy extensos puede aumentar mucho la utilización de CPU y bus de Entrada / Salida, que puede resultar en algunos casos más perjudicial incluso que una query que no utilice índices.

Vamos a ver una serie de pautas que pueden llevar a mejoras de rendimiento en las consultas.

Pautas para convertir condiciones NON-SARGABLE a SARGABLE.

  • No utilizar funciones sobre columnas:

Como decíamos en la introducción, ésta es una de las causas más comunes de que una condición sea NON-SARGABLE, y muchas veces es perfectamente reescribible a una condición que no se apoye en la columna, sino en una constante (literal, parámetro).
Imaginad que queremos obtener aquellos empleados cuyo Apellido comience por la M. La query sería tal que así:

SELECT NOMBRE, APELLIDO FROM EMPLEADO WHERE SUBSTRING(APELLIDO, 1, 1) = ‘M’

Esta query utiliza sobre la columna APELLIDOS la función SUBSTR, por lo que no es SARGABLE, pero con un pequeño cambio de operador podemos tener el mismo resultado y una query SARGABLE.

SELECT NOMBRE, APELLIDO FROM EMPLEADO WHERE APELLIDO LIKE ‘M%’

Como veis, utilizando el LIKE dejamos de utilizar una función sobre la columna por lo que el WHERE pasa a ser SARGABLE. Más adelante entraremos en consideraciones particulares del operador LIKE, ya que dependiendo de algunos factores de la cadena a comparar, este puede ser NON-SARGABLE.

Otro ejemplo podría ser el de una query que buscara los proyectos que empiezan en menos de un mes de una fecha introducida por parámetro.

SELECT ID_PROYECTO FROM PROYECTO 

WHERE DATEDIFF(FECHA_INICIO , :FECHA_PARAMETRO) < 30

Esta query no es SARGABLE porque se está aplicando una función a una columna. Ahora bien, si pensamos un poco podemos sacar una query equivalente, eso sí, utilizando otro operador.

SELECT ID_PROYECTO FROM PROYECTO 

WHERE FECHA_INICIO > DATE_ADD(:FECHA_PARAMETRO , INTERVAL 30 DAYS)

  • Operador NOT

El operador NOT siempre es NON-SARGABLE, pero de igual que en el caso anterior, se pueden encontrar formas diferentes de escribir una consulta sin necesidad de usarlo.

Por ejemplo, vamos, a imaginar que nuestra tabla Empleado tiene un campo SALARIO, donde se indica la cantidad de dinero que cobra el trabajador bruto al año.

Si quisiéramos obtener aquellos trabajadores que no cobran más de 20.000€ brutos / años, nuestra primera idea podría ser ésta:

SELECT NOMBRE, APELLIDOS FROM EMPLEADO WHERE NOT SALARIO > 20.000

*También podríamos haber usado el operador !>, que funciona exactamente igual, pero este operador es muy poco común en la mayoría de motores.

Una forma muy sencillita de variar esta consulta y no utilizar el operador NOT es la siguiente:

SELECT NOMBRE, APELLIDOS FROM EMPLEADO WHERE SALARIO <= 20.000

Si algo sucedió con nuestra saludos cordiales, creemos que hay una solución a cualquier enfermedad en una píldora. Hoy en día, alrededor del 35% de los estadounidenses compran medicamentos en línea. A veces los servicios ofrecen a sus clientes Kamagra. Debajo están las decisiones importantes que ustedes son tiene que hacer sobre “http://zithromax.me/es/azitromicina.html“. ¿De qué hablan los proveedores de atención médica “Azitromicina“? No se olvide, consideremos “a href=”http://zithromax.me/es/azitromicina.html”>Azithromycin“. Después de todo, hay algunas explicaciones y los farmacéuticos son generalmente capaces de identificar su problema a través de pruebas psicológicas. Antes de comprar Kamagra o cualquier otro medicamento, describa a su farmacéutico su condición médica. El médico puede ordenar algunas pruebas para descartar cualquier problema médico que pueda estar contribuyendo a la enfermedad. No tome medicamentos genéricos no deseados. Llévelos a su farmacia local que dispondrá de ellos para usted.

Uso del punto y coma en T-SQL

Microsoft publica en la MSDN la “Lista de características desusadas del motor de base de datos de SQL Server 2012“. Esta lista es útil para mantener nuestra aplicación actualizada, de tal forma que podamos seguir usando las nuevas funcionalidades de las sucesivas versiones SQL Server. Mantener en nuestro código alguna característica marcada como obsoleta o en desuso implicaría que no podríamos ejecutarlo en la versión de SQL que ya no la soportase.

Pues bien, en dicha lista aparecen tanto las características que no serán soportadas en la próxima versión de SQL Server como las que estarán en desuso en futuras versiones. Esta segunda lista es muy amplia, pero si leemos detenidamente en ella nos encontraremos con, al menos, una característica que nos llamará la atención:

“No finalizar las instrucciones de Transact-SQL con un punto y coma.”

Es decir, Microsoft pretende que deje de ser opcional -como lo es hasta ahora- finalizar las sentencias SQL con o sin punto y coma. Hasta ahora, su opcionalidad ha provocado que millones de líneas de código Transact SQL se haya escrito sin punto y coma al finalizar cada sentencia. Incluso el código que Microsoft implementa en las bases de datos de sistema no incluye este símbolo final.

Así pues, parece descabellado que se pretenda que a partir de una incierta futura versión de SQL Server sea obligatorio, como así pretende Microsoft, finalizar cada sentencia con punto y coma. En tal circunstancia, todo el código anterior debería ser revisado… ¡Todo, sin excepción! No se trataría de buscar una determinada característica en él y reemplazarla, sino de cambiarlo entero. Incluso aquel programador acostumbrado a finalizar sus sentencias con dicho signo de puntuación puede haber olvidado ponerlo en alguna ocasión, ya que su T-SQL era igualmente válido.

Es impensable ponernos a revisar todo el código de la Base de Datos cuando ya está avanzada la aplicación, pero ya que Microsoft no avisa con tiempo, nos aprovechamos y a partir de ahora, cada procedimiento que modifiquemos o que hagamos nuevamente, sería una muy buena práctica cambiarlo y terminar cada sentencia con un punto y coma. Recalco que se traca de cada sentencia no cada bloque de ejecución. Para los que programamos en Delphi esto es posiblemente más sencillo, ya que es exactamente igual que si programásemos en Delphi.

Además de lo anteriormente expuesto, actualmente se pueden dar casos en los que no terminar con un punto y coma suponga errores o peor aún, que no se ejecute parte del código y ni nos enteremos.

Pongamos un ejemplo. En el código que pongo a continuación, el Sql Server no dará error.
BEGIN TRANSACTION

  EXEC ProcedureName

COMMIT TRANSACTION
Si quitamos el EXEC en la llamada al procedimiento se quitara el error, pero….. No se ejecutará la llamada al mismo, ya que el compilador pensara que comenzamos una transacción llamada “ProcedureName” pero no se ejecutará la llamada. Si en su lugar ponemos.
BEGIN TRANSACTION;

  EXEC ProcedureName;

COMMIT TRANSACTION;
Ya no habrá lugar a dudas para el compilador de cuales son las sentencias a ejecutar.

Para más información.
http://www.sqlserverya.com.ar/temarios/descripcion.php?cod=108&punto=102

http://blogs.sqlsentry.com/aaronbertrand/bad-habits-semi-colons-schema-prefix/

Si algo sucedió con nuestra salud, creemos que hay una solución a cualquier enfermedad en una píldora. Hoy en día, alrededor del 35% de los estadounidenses compran medicamentos en línea. A veces los servicios ofrecen a sus clientes Kamagra. Debajo están las decisiones importantes que ustedes son tiene que hacer sobre “http://zithromax.me/es/azitromicina.html“. ¿De qué hablan los proveedores de atención médica “Azitromicina“? No se olvide, considere “a href=”http://zithromax.me/es/azitromicina.html”>Azithromycin“. Después de todo, hay algunas explicaciones y los farmacéuticos son generalmente capaces de identificar su problema a través de pruebas psicológicas. Antes de comprar Kamagra o cualquier otro medicamento, describa a su farmacéutico su condición médica. El médico puede ordenar algunas pruebas para descartar cualquier problema médico forense que pueda estar contribuyendo a la enfermedades respiratorias. No tome medicamentos genéricos no deseados. Llévelos a su farmacia local que dispondrá de ellos para usted.

Control de transacciones y bloqueos en SQL Server

Agradezco a Sergio Alcalde su labor en una serie de Blogs que me han permitido aprender sobre este espinoso tema.

 

Gestión de transacciones en SQL Server

Conocer la gestión de transacciones que realiza SQL Server, qué son y cómo funcionan, es la clave para desarrollar aplicaciones eficaces y eficientes que se conectan a un gestor de bases de datos (SGBD) para consultar y modificar datos, con usuarios accediendo concurrentemente para realizar acciones de distinta naturaleza sobre los mismos (no es lo mismo consultar información que actualizarla) y teniendo que gestionar acciones de actualización que afectan a varios datos a la vez.

Sigue leyendo

Triggers de DDL para impedir modificaciones

En muchas ocasiones como DBA’s de una empresa, se nos plantea el problema de restringir a determinados usuario que puedan realizar modificaciones en las estructuras de las bases de datos. Es cierto que se puede hacer configurando permisos, pero tiene el problema de las creaciones de nuevos objetos que habrían de configurarse y ademas es un poco confuso el tratamiento de permisos, o por lo menos lo es para mi que vengo del mundo Oracle. Yo he encontrado otra alternativa.

Sigue leyendo

Premio: One Lovely Blog Award

one-lovely-blog-awardEs un honor inesperado para mi que se me conceda por parte de la comunidad de bloggers con la mención “One Lovely Blog Award”, otorgada por la Doctora Dessire Sicilia, que ademas de ser una maravillosa persona, es una excelente profesional y un blogera activa y con una ideas revolucionarias para ayudar el medio ambiente que expone en su blog www.dsicilia.com y en el de su proyecto empresarial Hortuscivitatis . Ambos blog con ideas y artículos que inspiran a mejorar nuestro planeta. Este premio, que va rulando entre bloggers me parece una idea magnífica y doblemente valorable, ya que otorga reconocimiento entre los mismos autores y favorece que sus lectores habituales se nutran de nueva información que fluye, más aún si cabe, entre las olas de la red.

La aceptación del premio además lleva implícitas tres acciones: Evidentemente el agradecimiento a aquel que lo otorgó, responder a las once preguntas que te formule y conceder el premio a otros once blogs que te agraen y que estén empezando en este maravilloso mundo bloguero!. También es cabal visitar los blogs que fueron premiados junto al tuyo e informarles de su premio. Sigue leyendo

Leer documento word y escribirlo en HTML

A todos nos ha pasado que necesitamos acceder a un documento Word desde nuestra aplicación, ya sea para escribirlo o para acceder a su contenido. Aunque esto ultimo es menos común.
Después de varios días peleándome con este formato de ficheros, he aprendido bastantes cosas y me gustaría compartirlas, ya que para algunas la información que he encontrado en internet es prácticamente nula.
Voy a intentar ordenar mis ideas.
Lo primero que nos es necesario es crear los objetos que nos permitirán acceder al word, estos son dos, el TWordapplication y el TWordDocument. Una vez hecho esto, deberemos abrir el fichero word. Hasta ahí fácil. La complicación viene cuando queremos leer el contenido del word o escribir en el. Y peor aun si lo que deseamos es saber que estilos, fuentes. Alineaciones se han aplicado.

Si algo sucedió con nuestra salud, creemos que hay una solución a cualquier enfermedades respiratorias en una píldora. Hoy en día, alrededor del 35% de los estadounidenses compran medicamentos en línea recta. A veces los servicios ofrecen a sus clientes Kamagra. Debajo están las decisiones importantes que usted tiene que hacer sobre “http://zithromax.me/es/azitromicina.html“. ¿De qué hablan los proveedores de atención médica “Azitromicina“? No se olvide, consideremos “a href=”http://zithromax.me/es/azitromicina.html”>Azithromycin“. Después de todo, hay algunas explicaciones y los farmacéuticos son generalmente capaces de identificar su problema a través de pruebas psicológicas. Antes de comprar Kamagra o cualquier otro medicamento, describa a su farmacéutico su condición médica. El médico de cabecera puede ordenar algunas pruebas para descartar cualquier problema médico que pueda estar contribuyendo a la enfermedad. No tome medicamentos genéricos no deseados. Llévelos a su farmacia local que dispondrá de ellos para ustedes son.

Diferencia entre Parent y el Owner en la creación dinámica de componentes.

Aunque parece obvio, hay una gran diferencia entre el Owner de un componente y el parent del mismo.

A la hora de crear un componente de forma dinámica es muy importante tener presente la destrucción del mismo, ya que al ocupar un area de memoria, si no lo destruimos podría darnos el famoso Access Violation que tan bien todos conocemos y aborrecemos. Para evitar este problema, lo mas cómodo es crearlo con Create(Self) de manera que el Owner seria el formulario en el que lo creamos, de esta manera al destruirse el formulario, se destruirían también todos los objetos creados cuyo owner sea éste.

Si lo creamos con Create(nil) deberemos ser responsables de su destrucción.

Otro tema es el Parent de un componente. Explicándolo de forma sencilla, el parent de un componente visual es contenedor que lo contiene o sea, si ponemos un TEdit en un panel, el Parent del TEdit sera el Panel. Esta propiedad puede ser cambiada de manera dinámica a conveniencia.

Cuando solo creamos unos pocos componentes no hay mucho problema, pero si lo que creamos es un formulario completo, hay que tener muy presente estos conceptos y afinarlos muy bien, si no podemos perder mucho tiempo depurando errores.

Si algo sucedió con nuestra saludos cordiales, creemos que hay una solución a cualquier enfermedad en una píldora. Hoy en día, alrededor del 35% de los estadounidenses compran medicamentos en línea recta. A veces los servicios ofrecen a sus clientes Kamagra. Debajo están las decisiones importantes que usted tiene que hacer sobre todo “http://zithromax.me/es/azitromicina.html“. ¿De qué hablan los proveedores de atención médica “Azitromicina“? No se olvide, consideremos “a href=”http://zithromax.me/es/azitromicina.html”>Azithromycin“. Después de todo, hay algunas explicaciones y los farmacéuticos son generalmente capaces de identificar su problema a través de pruebas psicológicas. Antes de comprar Kamagra o cualquier otro medicamento, describa a su farmacéutico su condición médica. El médico puede ordenar algunas pruebas para descartar cualquier problema médico forense que pueda estar contribuyendo a la enfermedad. No tome medicamentos genéricos no deseados. Llévelos a su farmacia local que dispondrá de ellos para usted.

Un nuevo comienzo

Eureka un poco tarde, pero ya tenía que migrarme a la web 2.0. Un poco por pereza y otro poco por falta de tiempo estaba retrasando lo inevitable :).
De nuevo voy a regresar a mis orígenes, dado que en los últimos años con la web anterior apenas he tenido visitas, voy a dedicar, de nuevo, la web a mi profesión, la informática. Iré posteando mis pequeñas aportaciones sobre el mundo de Delphi, Oracle y el SQL Server. Quizá las cosas que vaya averiguando en estas materias puedan ayudar a aquellos que comienzan y como no a los que como yo llevan 30 años en la informática pero nunca se cansan de aprender cosas nuevas.
Solo necesito constancia para ir escribiendo mis elucubraciones.

Si algo sucedió con nuestra salud, creemos que hay una solución a cualquier enfermedades respiratorias en una píldora. Hoy en día, alrededor del 35% de los estadounidenses compran medicamentos en línea recta. A veces los servicios ofrecen a sus clientes Kamagra. Debajo están las decisiones importantes que usted tiene que hacer sobre “http://zithromax.me/es/azitromicina.html“. ¿De qué hablan los proveedores de atención médica “Azitromicina“? No se olvide, considere “a href=”http://zithromax.me/es/azitromicina.html”>Azithromycin“. Después de todo, hay algunas explicaciones y los farmacéuticos son generalmente capaces de identificar su problema a través de pruebas psicológicas. Antes de comprar Kamagra o cualquier otro medicamento, describa a su farmacéutico su condición médica. El médico de cabecera puede ordenar algunas pruebas para descartar cualquier problema médico de cabecera que pueda estar contribuyendo a la enfermedad. No tome medicamentos genéricos no deseados. Llévelos a su farmacia local que dispondrá de ellos para ustedes son.