¿como evitar los hot blocks?

04/05/2008 - 18:38 por AntonioFox | Informe spam
¿Que tal?

Estaba traspasando una clasica tabla de contadores (donde llevo contador
de facturas, documentos de venta, pedidos ...) a SQL Server y leo que
esta practica no es recomendada por el problema de los hot blocks

Entonses ¿que me recomienda para no tener el problema de los hot blocks
y como hago para tambien tener mis contadores? No me valen identities ya
que nesecito que me genere numeros realez

Gracias

AntonioFox

Preguntas similare

Leer las respuestas

#26 Maxi
05/05/2008 - 20:32 | Informe spam
Don't feed the troll ;-)


-
Microsoft M.V.P en SQLServer
SQLTotal Consulting - Servicios en SQLServer
Email:
"Gux (MVP)" escribió en el mensaje
news:

"Alfredo Novoa" wrote:

On Mon, 5 May 2008 08:44:00 -0700, Gux (MVP)
wrote:

>En lo que respecta a usar tablas numeradoras, me parece una buena opción
>para ciertos escenarios donde el usuario quiere por ejemplo, renumerar
>un
>cierto valor ("quiero que ahora las facturas se numeren a partir de X,
>lo
>quiero lo quiero lo quiero ya" :-)).

Pues haces un update y listo. No necesitas las tablas numeradoras para
eso.




Por ejemplo, supongamos que la aplicación tiene una tabla Factura que
tiene
una columna Numero (el número único de cada factura). Imaginemos estos
datos:

FACTURA (Numero, ... otros datos de factura ...)
1 datos2
2 datos4
3 datos6

Asumo ahora que la aplicación que inserta una nueva factura,
automáticamente
obtiene normalmente el Numero a insertra mediante un MAX(Numero) + 1.
Asumo
que se hacen los aislamientos necesarios para que dicho número no
colisione
con otra transacción intentando insertar una factura.

El usuario hoy quiere que las facturas empiecen a partir de 100, sin
alterar
las facturas viejas. No vale hacer un UPDATE a la Factura 3 ni insertar
una
factura ficticia 100.

No me doy cuenta cómo hacerlo con un UPDATE, cómo dice usted que podría
hacerse?

Gracias, saludos
~gux



Respuesta Responder a este mensaje
#27 Leonardo Azpurua
05/05/2008 - 21:02 | Informe spam
"Maxi" escribió en el mensaje
news:
Don't feed the troll ;-)



There's no troll.

Y en cualquier caso, la mejor manera de impulsar a una persona a comportarse
como un troll es hacer este tipo de comentarios, mucho peor si van
acompañados de guiñitos de complicidad.

Respeta a la gente y serás respetado.

Si tienes algun comentario despectivo que hacer con Gustavo acerca de un
tercero, hazlo por correo. Me parece de pésimo gusto -y hasta cierto punto
denigrante para la condicion de MVP- negarle el debido respeto a cualquier
participante del foro.

Don't be a troll ;-)


Salud!
Respuesta Responder a este mensaje
#28 Maxi
05/05/2008 - 21:10 | Informe spam
Tienes razon! fue solo un chiste :-) pido disculpas, no creo que sea para
tanto Leo :-S


-
Microsoft M.V.P en SQLServer
SQLTotal Consulting - Servicios en SQLServer
Email:
"Leonardo Azpurua" <l e o n a r d o [arroba] m v p s [punto] o r g> escribió
en el mensaje news:

"Maxi" escribió en el mensaje
news:
Don't feed the troll ;-)



There's no troll.

Y en cualquier caso, la mejor manera de impulsar a una persona a
comportarse como un troll es hacer este tipo de comentarios, mucho peor si
van acompañados de guiñitos de complicidad.

Respeta a la gente y serás respetado.

Si tienes algun comentario despectivo que hacer con Gustavo acerca de un
tercero, hazlo por correo. Me parece de pésimo gusto -y hasta cierto punto
denigrante para la condicion de MVP- negarle el debido respeto a cualquier
participante del foro.

Don't be a troll ;-)


Salud!


Respuesta Responder a este mensaje
#29 Gux (MVP)
05/05/2008 - 21:30 | Informe spam
De la siguiente manera ejecutó correctamente sin violaciones de PK ni
deadlocks:


USE tempdb
GO

DECLARE @i INT

SET @i = 1

WAITFOR TIME '16:26:00'

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE

WHILE @i <= 1000
BEGIN
BEGIN TRANSACTION

INSERT INTO dbo.t1 (contador, [id])
VALUES ('contador 1', (SELECT MAX(id) + 1
FROM dbo.t1 WITH (TABLOCK)
WHERE contador = 'contador 1'))

COMMIT TRANSACTION

SET @i = @i + 1
END

SET TRANSACTION ISOLATION LEVEL READ COMMITTED
GO




USE tempdb
GO

DECLARE @i INT

SET @i = 1

WAITFOR TIME '16:26:00'

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE

WHILE @i <= 1000
BEGIN
BEGIN TRANSACTION

INSERT INTO dbo.t1 (contador, [id])
VALUES ('contador 1', (SELECT MAX(id) + 1
FROM dbo.t1 WITH (TABLOCK)
WHERE contador = 'contador 1'))

COMMIT TRANSACTION

SET @i = @i + 1
END

SET TRANSACTION ISOLATION LEVEL READ COMMITTED
GO


Gustavo Larriera, Microsoft MVP
https://mvp.support.microsoft.com/p...o.larriera
Este mensaje se proporciona tal como es, sin garantías de ninguna clase.



"Alejandro Mesa" wrote:

Gux,

Te lo dejo de prueba, veras lo que pasa cuando usas SERIALIZABLE .


AMB

"Gux (MVP)" wrote:

> Gracias por el código Alejandro. Intentaré probarlo en cuanto esté en una
> máquina con SQL instalado.
>
> Seré curioso, antes de probar tu código: El isolation level no debería ser
> SERIALIZABLE ?
>
> Gustavo Larriera, Microsoft MVP
> https://mvp.support.microsoft.com/p...o.larriera
> Este mensaje se proporciona tal como es, sin garantías de ninguna clase.
>
>
>
> "Alejandro Mesa" wrote:
>
> > Hola Gustavo,
> >
> > Que tal si probamos con codigo.
> >
> > Sesion 1:
> >
> > use tempdb
> > go
> >
> > DROP TABLE dbo.t1
> > GO
> >
> > CREATE TABLE dbo.t1 (
> > transaccion_id INT NOT NULL IDENTITY PRIMARY KEY,
> > dt DATETIME NOT NULL DEFAULT(GETDATE()),
> > contador VARCHAR(25) NOT NULL,
> > [id] INT NOT NULL,
> > CONSTRAINT UQ_transaccion_contador_id UNIQUE (contador, id)
> > )
> > GO
> >
> > INSERT INTO dbo.t1 (contador, id) VALUES('contador 1', 1)
> > GO
> >
> > Antes de ejecutar esta parte, favor usar un tiempo no lejano en el futuro
> > para que ambas sesiones ejecuten este codigo al mismo tiempo.
> >
> > DECLARE @i INT
> >
> > SET @i = 1
> >
> > WAITFOR TIME '13:15:00'
> >
> > SET TRANSACTION ISOLATION LEVEL READ COMMITTED
> >
> > WHILE @i <= 1000
> > BEGIN
> > BEGIN TRANSACTION
> >
> > INSERT INTO dbo.t1 (
> > contador,
> > [id]
> > )
> > SELECT 'contador 1', MAX(id) + 1
> > FROM dbo.t1 AS c
> > WHERE contador = 'contador 1'
> >
> > COMMIT TRANSACTION
> >
> > SET @i = @i + 1
> > END
> >
> > SET TRANSACTION ISOLATION LEVEL READ COMMITTED
> > GO
> >
> > Session 2
> >
> > use tempdb
> > go
> >
> > DECLARE @i INT
> >
> > SET @i = 1
> >
> > WAITFOR TIME '13:15:00'
> >
> > SET TRANSACTION ISOLATION LEVEL READ COMMITTED
> >
> > WHILE @i <= 1000
> > BEGIN
> > BEGIN TRANSACTION
> >
> > INSERT INTO dbo.t1 (
> > contador,
> > [id]
> > )
> > SELECT 'contador 1', MAX(id) + 1
> > FROM dbo.t1 AS c
> > WHERE contador = 'contador 1'
> >
> > COMMIT TRANSACTION
> >
> > SET @i = @i + 1
> > END
> >
> > SET TRANSACTION ISOLATION LEVEL READ COMMITTED
> > GO
> >
> > Si creen que el nivel READ COMMITTED no es suficiente, entonces cambienlo en
> > ambas sessiones y vean los resultados.
> >
> >
> > AMB
> >
> > "Gux (MVP)" wrote:
> >
> > > "Alfredo Novoa" wrote:
> > >
> > > > wrote:
> > > >
> > > > >Hola Antonio, a mi me parece correcto usar la tabla numeradora y los
> > > > >bloqueos, a la larga es lo mas eficiente que podes hacer y seguro. Si haces
> > > > >un Max sobre la tabla y esta tiene millones de registros no va a ser tan
> > > > >rapido como hacer un update sobre la tabla numeradora de unos pocos
> > > > >registros.
> > > >
> > > > ¿Por que?
> > > >
> > > > Para eso están los índices.
> > >
> > > Exacto.
> > >
> > > Si hay una consulta que usa funciones agregadas (mi libre traducción de
> > > "aggregate" :-)) considerar el uso de un índice no-clustered. Estos índices
> > > incluyen una fila con el valor de índice para cálculos agregados, por lo que
> > > SQL Server no necesita acceder a la tabla real para hacer el cálculo de la
> > > función.
> > >
> > >
> > > Gustavo Larriera, Microsoft MVP
> > > https://mvp.support.microsoft.com/p...o.larriera
> > > Este mensaje se proporciona tal como es, sin garantías de ninguna clase.
> > >
> > >
> > >
> > > "Alfredo Novoa" wrote:
> > >
> > > >
> > > > Hola Maxi,
> > > >
> > > > On Mon, 5 May 2008 10:53:28 -0300, "Maxi"
> > > > wrote:
> > > >
> > > > >Hola Antonio, a mi me parece correcto usar la tabla numeradora y los
> > > > >bloqueos, a la larga es lo mas eficiente que podes hacer y seguro. Si haces
> > > > >un Max sobre la tabla y esta tiene millones de registros no va a ser tan
> > > > >rapido como hacer un update sobre la tabla numeradora de unos pocos
> > > > >registros.
> > > >
> > > > ¿Por que?
> > > >
> > > > Para eso están los índices.
> > > >
> > > > >aplicaciones por el costo a nivel performance que tiene eso, ademas de que
> > > > >estarias haciendo un select y si dos hacen el mismo Max y no consideras
> > > > >otras cosas a nivel bloqueo podria darles el mismo numero)
> > > >
> > > > ¿Que más habría que considerar?
> > > >
> > > >
> > > >
> > > > Saludos
> > > >
Respuesta Responder a este mensaje
#30 Salvador Ramos
05/05/2008 - 21:49 | Informe spam
Hola Alfredo,

A esa alternativa le veo problemas de obtencion valores max duplicados en
casos de mucha concurrencia.

Un saludo
Salvador Ramos
Solid Quality Mentors (http://www.solidq.com)

www.helpdna.net (informacion sobre SQL Server y Microsoft .Net)
Visita mi nuevo blog: www.sqlserversi.com


"Alfredo Novoa" escribio en el mensaje
news:

Hola Leonardo,

El Sun, 4 May 2008 12:57:59 -0430, Leonardo Azpurua escribi?:

Mas sensato es:

TipoDoc char(X)
ProximoNumero Bigint,

usando bloqueos a nivel de registro (que creo que es la conducta por
omisi??


de SQL Server).

?Y por que no hacemos un simple:

insert into tabla select max(Id) + 1 from tabla, ...

Y as? nos ahorramos la tabla de contadores.


Saludos
Alfredo
Respuesta Responder a este mensaje
Ads by Google
Help Hacer una preguntaSiguiente AnteriorRespuesta Tengo una respuesta
Search Busqueda sugerida