forzar uso de un indice u otra solucion

13/11/2005 - 10:44 por yodelmis | Informe spam
saludos



tengo la siguiente tabla : ControlAcc (ID long ,Fecha date, Persona
varchar(30),Destino varchar(30),Autori int)
con indices creados por (ID),(Fecha),(Fecha,Persona,Destino,Autori), este
ultimo indice fue sugerido por sql.

El problema es el siguiente:

Cuando realizo una busqueda por rango de fecha, la busqueda se demora
demaciado y en el caso de una solo fecha la respuesta es inmediata. Cuando
voy al plan de ejecucion, me doy cuenta que en el caso de la busqueda por
rango de fecha, el sqlserver no esta utilizando el indice de fecha.

Existe alguna forma de forzar a que en este caso sqlserver utilize el indice
de fecha.

Preguntas similare

Leer las respuestas

#1 Maxi [MVP]
13/11/2005 - 12:31 | Informe spam
Hola existir existe una forma pero no te la recomiendo en lo absolut. Me
imagino que este es un solo indice compuesto por todos estos campos no o
tienes mas de un indice? podrias poner el plan de ejecucion? otra cosa, las
estadisticas las tienes actualizadas no?


Salu2
-
[MVP] SQL Server
Orador para Culminis Latam
Miembro de GUESS



"yodelmis" escribió en el mensaje
news:%
saludos



tengo la siguiente tabla : ControlAcc (ID long ,Fecha date, Persona
varchar(30),Destino varchar(30),Autori int)
con indices creados por (ID),(Fecha),(Fecha,Persona,Destino,Autori), este
ultimo indice fue sugerido por sql.

El problema es el siguiente:

Cuando realizo una busqueda por rango de fecha, la busqueda se demora
demaciado y en el caso de una solo fecha la respuesta es inmediata. Cuando
voy al plan de ejecucion, me doy cuenta que en el caso de la busqueda por
rango de fecha, el sqlserver no esta utilizando el indice de fecha.

Existe alguna forma de forzar a que en este caso sqlserver utilize el
indice de fecha.

Respuesta Responder a este mensaje
#2 Alejandro Mesa
13/11/2005 - 16:35 | Informe spam
yodelmis,

Nos dijistes los indices que tienes, pero no nos dijistes que tipo de indice
es cada cual. Tampoco nos has dicho cual(es) columna(s) conforman la clave
primaria y si tienes alguna restriccion de tipo "unique". Quizas el indice
que tienes por [ID] es de tipo clustered, el cual es el indice que usa sql
server para selecciones de rango, debido a que las paginas de data esta
enlazadas de forma ordenada. En cambio, los indices nonclustered son utiles
para selecciones de pocas filas, y de seguro el indice por [Fecha], al igual
que el indice por (Fecha,Persona,Destino,Autori) son de tipo nonclustered. Es
por eso que se debe hacer un analisis de las sentencias "select" en base a
frequencia y prioridad, antes de escojer el tipo de indice y las columnas que
conformaran la clave.

Podrias hacer una prueba y desabilitar la restricciones de clave foranea, en
qcaso de que exista alguna que referencie la columna [ID] de esa tabla,
eliminas la restricion de clave primaria para que puedas eliminar ese indice,
elimines los otros indices nonclustered, crees un indice clustered por
[Fecha] y recress los otros indices como nonclustered, y habilites nuevamente
las restricciones de clave foranea.

Aca paso un ejemplo para mostrar lo comentado.

use northwind
go

select orderid, customerid, orderdate
into dbo.t1
from dbo.orders
go

create unique clustered index ix_u_c_t1_orderid on t1(orderid asc)
go

create nonclustered index ix_nc_t1_orderdate on t1(orderdate asc)
go

set showplan_text on
go

select *
from dbo.t1
where orderdate between '19970101' and '19971231'
go

set showplan_text off
go

drop index dbo.t1.ix_nc_t1_orderdate
drop index dbo.t1.ix_u_c_t1_orderid
go

create unique clustered index ix_u_c_t1_orderdate on t1(orderdate asc)
go

create nonclustered index ix_nc_t1_orderid on t1(orderid asc)
go

set showplan_text on
go

select *
from dbo.t1
where orderdate between '19970101' and '19971231'
go

set showplan_text off
go

drop table dbo.t1
go


AMB

"yodelmis" wrote:

saludos



tengo la siguiente tabla : ControlAcc (ID long ,Fecha date, Persona
varchar(30),Destino varchar(30),Autori int)
con indices creados por (ID),(Fecha),(Fecha,Persona,Destino,Autori), este
ultimo indice fue sugerido por sql.

El problema es el siguiente:

Cuando realizo una busqueda por rango de fecha, la busqueda se demora
demaciado y en el caso de una solo fecha la respuesta es inmediata. Cuando
voy al plan de ejecucion, me doy cuenta que en el caso de la busqueda por
rango de fecha, el sqlserver no esta utilizando el indice de fecha.

Existe alguna forma de forzar a que en este caso sqlserver utilize el indice
de fecha.



Respuesta Responder a este mensaje
#3 Alejandro Mesa
14/11/2005 - 01:16 | Informe spam
Voy a cambiar el script un poquito porque la cantidad de filas en t1 son
pocas (830) y ademas no todas son del anio 1997, por lo que la cantidad no es
representativa como para rechazar una busqueda atraves del indice
nonclustered.

use northwind
go

select orderid, customerid, orderdate
into dbo.t1
from dbo.orders
go

set identity_insert t1 on
go

insert t1 (orderid, customerid, orderdate)
select orderid + 10000, customerid, orderdate
into dbo.t1
from dbo.orders
go

insert t1 (orderid, customerid, orderdate)
select orderid + 20000, customerid, orderdate
into dbo.t1
from dbo.orders
go

set identity_insert t1 on
go

create unique clustered index ix_u_c_t1_orderid on t1(orderid asc)
go

create nonclustered index ix_nc_t1_orderdate on t1(orderdate asc)
go

set showplan_text on
go

select *
from dbo.t1
where orderdate between '19970101' and '19971231'
go

set showplan_text off
go

drop index dbo.t1.ix_nc_t1_orderdate
drop index dbo.t1.ix_u_c_t1_orderid
go

create unique clustered index ix_u_c_t1_orderdate on t1(orderdate asc)
go

create nonclustered index ix_nc_t1_orderid on t1(orderid asc)
go

set showplan_text on
go

select *
from dbo.t1
where orderdate between '19970101' and '19971231'
go

set showplan_text off
go

drop table dbo.t1
go

Fijate en el plan de ejecucion de la primera sentencia "select". SQL Server
escoje hacer un scan del indice clustered que es por orderid a pesar de
existir un indice nonclustered por orderdate. Que pasa con la segunda
sentencia "select?, sql server decide hacer un index seek en el indice
clustered por orderdate.


AMB

"Alejandro Mesa" wrote:

yodelmis,

Nos dijistes los indices que tienes, pero no nos dijistes que tipo de indice
es cada cual. Tampoco nos has dicho cual(es) columna(s) conforman la clave
primaria y si tienes alguna restriccion de tipo "unique". Quizas el indice
que tienes por [ID] es de tipo clustered, el cual es el indice que usa sql
server para selecciones de rango, debido a que las paginas de data esta
enlazadas de forma ordenada. En cambio, los indices nonclustered son utiles
para selecciones de pocas filas, y de seguro el indice por [Fecha], al igual
que el indice por (Fecha,Persona,Destino,Autori) son de tipo nonclustered. Es
por eso que se debe hacer un analisis de las sentencias "select" en base a
frequencia y prioridad, antes de escojer el tipo de indice y las columnas que
conformaran la clave.

Podrias hacer una prueba y desabilitar la restricciones de clave foranea, en
qcaso de que exista alguna que referencie la columna [ID] de esa tabla,
eliminas la restricion de clave primaria para que puedas eliminar ese indice,
elimines los otros indices nonclustered, crees un indice clustered por
[Fecha] y recress los otros indices como nonclustered, y habilites nuevamente
las restricciones de clave foranea.

Aca paso un ejemplo para mostrar lo comentado.

use northwind
go

select orderid, customerid, orderdate
into dbo.t1
from dbo.orders
go

create unique clustered index ix_u_c_t1_orderid on t1(orderid asc)
go

create nonclustered index ix_nc_t1_orderdate on t1(orderdate asc)
go

set showplan_text on
go

select *
from dbo.t1
where orderdate between '19970101' and '19971231'
go

set showplan_text off
go

drop index dbo.t1.ix_nc_t1_orderdate
drop index dbo.t1.ix_u_c_t1_orderid
go

create unique clustered index ix_u_c_t1_orderdate on t1(orderdate asc)
go

create nonclustered index ix_nc_t1_orderid on t1(orderid asc)
go

set showplan_text on
go

select *
from dbo.t1
where orderdate between '19970101' and '19971231'
go

set showplan_text off
go

drop table dbo.t1
go


AMB

"yodelmis" wrote:

> saludos
>
>
>
> tengo la siguiente tabla : ControlAcc (ID long ,Fecha date, Persona
> varchar(30),Destino varchar(30),Autori int)
> con indices creados por (ID),(Fecha),(Fecha,Persona,Destino,Autori), este
> ultimo indice fue sugerido por sql.
>
> El problema es el siguiente:
>
> Cuando realizo una busqueda por rango de fecha, la busqueda se demora
> demaciado y en el caso de una solo fecha la respuesta es inmediata. Cuando
> voy al plan de ejecucion, me doy cuenta que en el caso de la busqueda por
> rango de fecha, el sqlserver no esta utilizando el indice de fecha.
>
> Existe alguna forma de forzar a que en este caso sqlserver utilize el indice
> de fecha.
>
>
>
Respuesta Responder a este mensaje
#4 yodelmis
14/11/2005 - 03:11 | Informe spam
Gracias a todos por la ayuda

Maxi,
son 3 indices distintos y el ID es la llave primaria

Alejandro:

Intentare probar esta variante en cuanto llege a la oficina. Pero creo que
cuando marco un campo como clave primaria, SQL SERVER crea un indice
clauster con este campo, en mi caso ID es la llave primaria.

.
Respuesta Responder a este mensaje
#5 Alejandro Mesa
14/11/2005 - 14:53 | Informe spam
yodelmis,

Intentare probar esta variante en cuanto llege a la oficina. Pero creo que
cuando marco un campo como clave primaria, SQL SERVER crea un indice
clauster con este campo, en mi caso ID es la llave primaria.



Correcto, pero eso no significa que no puedas cambiar el tipo de indice que
usara la clave primaria. Si estas creando la clave primaria usando EM
(Enterprise Manager), puedes hacer click al boton "Manage Indexes/Keys...",
que es el segundo de deracha a izquierda en la barra de herramientas de la
ventana de disenios de la tabla, y en esa ventana puedes seleccionar o no la
opcion "Create as CLUSTERED". Si estas creando la clave primaria usando
codigo T-SQL, puedes especificar que tipo de indice sera usado por la clave
primaria.

Ejemplo:

create table t1 (
c1 int not null constraint pk_t1 primary key nonclustered
)
go

A la final, el EM creara un scrip T-SQL similar al anterior, el cual puedes
chequear si haces click al boton "Save change script", que es el tercero de
izquierda a derecha en la ventana de disenio de la tabla, antes de salvar los
cambios.

Ejemplo:

Si voy al EM, habro la tabla "orders" en modo de disenio y hago click en el
boton "Manage Indexes/Keys...", selecciono el indice PK_Orders (que es el
indice generado por sql server para la clave primaria), le quito la marca en
el check box que dice "Create as CLUSTERED", entonces EM ejecutara el
siguiente script:

BEGIN TRANSACTION
SET QUOTED_IDENTIFIER ON
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
SET ARITHABORT ON
SET NUMERIC_ROUNDABORT OFF
SET CONCAT_NULL_YIELDS_NULL ON
SET ANSI_NULLS ON
SET ANSI_PADDING ON
SET ANSI_WARNINGS ON
COMMIT
BEGIN TRANSACTION
ALTER TABLE dbo.[Order Details]
DROP CONSTRAINT FK_Order_Details_Orders
GO
ALTER TABLE dbo.Orders
DROP CONSTRAINT PK_Orders
GO
ALTER TABLE dbo.Orders ADD CONSTRAINT
PK_Orders PRIMARY KEY NONCLUSTERED
(
OrderID
) ON [PRIMARY]

GO
COMMIT
BEGIN TRANSACTION
ALTER TABLE dbo.[Order Details] WITH NOCHECK ADD CONSTRAINT
FK_Order_Details_Orders FOREIGN KEY
(
OrderID
) REFERENCES dbo.Orders
(
OrderID
)
GO
COMMIT
go


AMB

"yodelmis" wrote:

Gracias a todos por la ayuda

Maxi,
son 3 indices distintos y el ID es la llave primaria

Alejandro:

Intentare probar esta variante en cuanto llege a la oficina. Pero creo que
cuando marco un campo como clave primaria, SQL SERVER crea un indice
clauster con este campo, en mi caso ID es la llave primaria.

.



email Siga el debate Respuesta Responder a este mensaje
Ads by Google
Help Hacer una preguntaRespuesta Tengo una respuesta
Search Busqueda sugerida