Showing posts with label dbo. Show all posts
Showing posts with label dbo. Show all posts

Friday, March 30, 2012

Index Tuning

Hi All!
I have this table:
CREATE TABLE [dbo].[Constructions] (
[ConstructionID] [int] IDENTITY (1, 1) NOT NULL , --PK
[TypeID] [int] NOT NULL ,
[TerritoryID] [int] NOT NULL,
[BeginDate] [datetime] NOT NULL ,
[EndDate] [datetime] NOT NULL ,
[IsCancelled] [bit] NOT NULL
) ON [PRIMARY]
With over 1.000.000 records and daily inserts of 10.000 records.
The fields that are updated by users from time to time are BeginDate,
EndDate and IsCancelled.
This is a table of an online database and the indexes could by rebuild once
a day or so.
Here is the question:
What index would be the appropriate for this type of query (highly used):
SELECT
ConstructionID, TypeID, TerritoryID, BeginDate, EndDate
FROM
Constructions
WHERE
TerritoryID = @.TerritoryID
AND
EndDate < GETDATE()
AND
IsCancelled = 0I guess
1) Create an index on any very selective column. If something is very
selective then that's the only index you need!
2) Create in index on any combination of selective criteria. You don't need
everything from the WHERE clause but try and supply the combination of
columns that will yield a selective set!
3) If nothing is selective - even when combined - then cover the query!
"Jorgebg" <Jorgebg@.discussions.microsoft.com> wrote in message
news:C72F8FBF-5E27-4271-A5DA-BD2DD8A3AD3B@.microsoft.com...
> Hi All!
> I have this table:
> CREATE TABLE [dbo].[Constructions] (
> [ConstructionID] [int] IDENTITY (1, 1) NOT NULL , --PK
> [TypeID] [int] NOT NULL ,
> [TerritoryID] [int] NOT NULL,
> [BeginDate] [datetime] NOT NULL ,
> [EndDate] [datetime] NOT NULL ,
> [IsCancelled] [bit] NOT NULL
> ) ON [PRIMARY]
> With over 1.000.000 records and daily inserts of 10.000 records.
> The fields that are updated by users from time to time are BeginDate,
> EndDate and IsCancelled.
> This is a table of an online database and the indexes could by rebuild
> once
> a day or so.
> Here is the question:
> What index would be the appropriate for this type of query (highly used):
> SELECT
> ConstructionID, TypeID, TerritoryID, BeginDate, EndDate
> FROM
> Constructions
> WHERE
> TerritoryID = @.TerritoryID
> AND
> EndDate < GETDATE()
> AND
> IsCancelled = 0|||It is pure guesswork without being able to analyze the actual data in
the table, but I suspect that an index on (TerritoryID, IsCancelled,
EndDate) would be a good place to start.
If I had access to the table I would be trying to get a feel for the
data by running queries along the lines of:
select IsCancelled, count(*) as rows
from Constructions
group by IsCancelled
select count(distinct TerritoryID) from Constructions
select TerritoryID, count(*) as rows,
sum(case when IsCancelled = 1 then 1 else 0 end) as Cancelled
from Constructions
group by TerritoryID
order by 2 desc
The idea behind queries like this is to start to understand the data.
This includes how selective each column is and how evenly distributed
the data is. A table with 100 values for TerritoryID is one thing,
but if 1 TerritoryID out of the hundred has 80% of all rows that is
something else. Likewise knowing if 1%, or 50%, or 99% of the rows
are cancelled makes rather a large difference.
Roy Harvey
Beacon Falls, CT
On Tue, 6 Jun 2006 02:21:01 -0700, Jorgebg
<Jorgebg@.discussions.microsoft.com> wrote:

>Hi All!
>I have this table:
>CREATE TABLE [dbo].[Constructions] (
> [ConstructionID] [int] IDENTITY (1, 1) NOT NULL , --PK
> [TypeID] [int] NOT NULL ,
> [TerritoryID] [int] NOT NULL,
> [BeginDate] [datetime] NOT NULL ,
> [EndDate] [datetime] NOT NULL ,
> [IsCancelled] [bit] NOT NULL
> ) ON [PRIMARY]
>With over 1.000.000 records and daily inserts of 10.000 records.
>The fields that are updated by users from time to time are BeginDate,
>EndDate and IsCancelled.
>This is a table of an online database and the indexes could by rebuild once
>a day or so.
>Here is the question:
>What index would be the appropriate for this type of query (highly used):
>SELECT
> ConstructionID, TypeID, TerritoryID, BeginDate, EndDate
>FROM
> Constructions
>WHERE
> TerritoryID = @.TerritoryID
> AND
> EndDate < GETDATE()
> AND
> IsCancelled = 0|||These are good suggestions. Alternatively, you could try using the Database
Tuning Advisor (or the Indexing Tuning Wizard in SQL Server 2000) to tune
your indexes for your whole workload.
SQL Server 2005 also includes the "Missing Indexes" feature which is
suitable for the task. Check the SQL Server 2005 Books Online for details on
the above options.
Regards,
Leo
"Roy Harvey" <roy_harvey@.snet.net> wrote in message
news:4joa825gpkmpqe6ojmm2ig00fs338873f9@.
4ax.com...
> It is pure guesswork without being able to analyze the actual data in
> the table, but I suspect that an index on (TerritoryID, IsCancelled,
> EndDate) would be a good place to start.
> If I had access to the table I would be trying to get a feel for the
> data by running queries along the lines of:
> select IsCancelled, count(*) as rows
> from Constructions
> group by IsCancelled
> select count(distinct TerritoryID) from Constructions
> select TerritoryID, count(*) as rows,
> sum(case when IsCancelled = 1 then 1 else 0 end) as Cancelled
> from Constructions
> group by TerritoryID
> order by 2 desc
> The idea behind queries like this is to start to understand the data.
> This includes how selective each column is and how evenly distributed
> the data is. A table with 100 values for TerritoryID is one thing,
> but if 1 TerritoryID out of the hundred has 80% of all rows that is
> something else. Likewise knowing if 1%, or 50%, or 99% of the rows
> are cancelled makes rather a large difference.
> Roy Harvey
> Beacon Falls, CT
>
> On Tue, 6 Jun 2006 02:21:01 -0700, Jorgebg
> <Jorgebg@.discussions.microsoft.com> wrote:
>|||On Tue, 6 Jun 2006 02:21:01 -0700, Jorgebg wrote:

>Hi All!
>I have this table:
>CREATE TABLE [dbo].[Constructions] (
> [ConstructionID] [int] IDENTITY (1, 1) NOT NULL , --PK
> [TypeID] [int] NOT NULL ,
> [TerritoryID] [int] NOT NULL,
> [BeginDate] [datetime] NOT NULL ,
> [EndDate] [datetime] NOT NULL ,
> [IsCancelled] [bit] NOT NULL
> ) ON [PRIMARY]
Hi Jorgebg,
The "--PK" comment suggests that the IDENTITY column is the primary key,
but you didn't declare it as such. SQL Server will not automatically
define a PRIMARY KEY constsaint for IDENTITY columns.
In addition to the identity surrogate key, your table should also have a
business key (and you should declare a UNIQUE constraint for it).
(snip)
>Here is the question:
>What index would be the appropriate for this type of query (highly used):
>SELECT
> ConstructionID, TypeID, TerritoryID, BeginDate, EndDate
>FROM
> Constructions
>WHERE
> TerritoryID = @.TerritoryID
> AND
> EndDate < GETDATE()
> AND
> IsCancelled = 0
Suggestion 1:
CREATE NONCLUSTERED INDEX ix1
ON Constructions (TerritoryID, IsCancelled, EndDate)
Suggestion 2 - assuming you don't have a CLUSUTERED index, or that you
can change it:
CREATE CLUSTERED INDEX ix2
ON Constructions (TerritoryID, IsCancelled, EndDate)
Suggestion 3.1 - assuming you have a CLUSTERED index on ConstructionID
and don't want to change it, AND assuming you're using SQL Server 2000:
CREATE NONCLUSTERED INDEX ix3_1
ON Constructions (TerritoryID, IsCancelled, EndDate, TypeID,
BeginDate)
Suggestion 3.2 assuming you have a CLUSTERED index on ConstructionID and
don't want to change it, AND assuming you're using SQL Server 2005
CREATE NONCLUSTERED INDEX ix3_1
ON Constructions (TerritoryID, IsCancelled, EndDate)
INCLUDE (TypeID, BeginDate)
Hugo Kornelis, SQL Server MVP|||I may be mistaken, but since isCancelled is a bit column, it is a poor
choice for an index. In fact, I don't think SQL Server will even allow it
(at least it does not on 2000). Otherwise, the advice you have gotten so
far should get you the performance that you need.
"Hugo Kornelis" <hugo@.perFact.REMOVETHIS.info.INVALID> wrote in message
news:ti9d82d667kunlbek0mrfu6midipucq7g7@.
4ax.com...
> On Tue, 6 Jun 2006 02:21:01 -0700, Jorgebg wrote:
>
> Hi Jorgebg,
> The "--PK" comment suggests that the IDENTITY column is the primary key,
> but you didn't declare it as such. SQL Server will not automatically
> define a PRIMARY KEY constsaint for IDENTITY columns.
> In addition to the identity surrogate key, your table should also have a
> business key (and you should declare a UNIQUE constraint for it).
> (snip)
> Suggestion 1:
> CREATE NONCLUSTERED INDEX ix1
> ON Constructions (TerritoryID, IsCancelled, EndDate)
> Suggestion 2 - assuming you don't have a CLUSUTERED index, or that you
> can change it:
> CREATE CLUSTERED INDEX ix2
> ON Constructions (TerritoryID, IsCancelled, EndDate)
> Suggestion 3.1 - assuming you have a CLUSTERED index on ConstructionID
> and don't want to change it, AND assuming you're using SQL Server 2000:
> CREATE NONCLUSTERED INDEX ix3_1
> ON Constructions (TerritoryID, IsCancelled, EndDate, TypeID,
> BeginDate)
> Suggestion 3.2 assuming you have a CLUSTERED index on ConstructionID and
> don't want to change it, AND assuming you're using SQL Server 2005
> CREATE NONCLUSTERED INDEX ix3_1
> ON Constructions (TerritoryID, IsCancelled, EndDate)
> INCLUDE (TypeID, BeginDate)
>
> --
> Hugo Kornelis, SQL Server MVP|||On Wed, 7 Jun 2006 10:44:48 -0400, Jim Underwood wrote:

>I may be mistaken, but since isCancelled is a bit column, it is a poor
>choice for an index. In fact, I don't think SQL Server will even allow it
>(at least it does not on 2000).
Hi Jim,
Sorry, but you are wrong. Here's a script to prove it. If you execute
just the two SELECT statements with the option to show execution plan
on, you'll see that the index is not only create but also used.
CREATE TABLE BitTest
(PKCol int NOT NULL IDENTITY PRIMARY KEY,
BitCol bit NOT NULL)
go
CREATE INDEX x_bit ON BitTest (BitCol)
go
INSERT INTO BitTest (BitCol) VALUES (0)
INSERT INTO BitTest (BitCol) VALUES (0)
INSERT INTO BitTest (BitCol) VALUES (1)
INSERT INTO BitTest (BitCol) VALUES (1)
INSERT INTO BitTest (BitCol) VALUES (0)
INSERT INTO BitTest (BitCol) VALUES (1)
INSERT INTO BitTest (BitCol) VALUES (0)
go
-- Searched query - uses index s on x_bit
SELECT * FROM BitTest WHERE BitCol = CAST(1 AS bit)
-- Query w/o WHERE - uses index scan on x_bit
SELECT * FROM BitTest
go
DROP TABLE BitTest
go
Here's the version of SQL Server I tested this on:
SELECT @.@.Version
go
Microsoft SQL Server 2000 - 8.00.2187 (Intel X86)
Mar 9 2006 11:38:51
Copyright (c) 1988-2003 Microsoft Corporation
Developer Edition on Windows NT 5.1 (Build 2600: Service Pack 2)
Hugo Kornelis, SQL Server MVP|||Hugo,
Thanks for that example. The results were identical on my installation.
I was misled by this quote from BOL.
bit
Integer data type 1, 0, or NULL.
Remarks
Columns of type bit cannot have indexes on them.
That will teach me to take BOL for granted without testing first.
That said, would it be preferable to put the bit col as the last column in
the index, after EndDate? Where EndDate will be more selective than
isCancelled? Unless, of course, isCancelled has very few values of 0.
"Hugo Kornelis" <hugo@.perFact.REMOVETHIS.info.INVALID> wrote in message
news:tqfe82p289pqt02752cshltfhaoroubl4n@.
4ax.com...
> On Wed, 7 Jun 2006 10:44:48 -0400, Jim Underwood wrote:
>
it
> Hi Jim,
> Sorry, but you are wrong. Here's a script to prove it. If you execute
> just the two SELECT statements with the option to show execution plan
> on, you'll see that the index is not only create but also used.
> CREATE TABLE BitTest
> (PKCol int NOT NULL IDENTITY PRIMARY KEY,
> BitCol bit NOT NULL)
> go
> CREATE INDEX x_bit ON BitTest (BitCol)
> go
> INSERT INTO BitTest (BitCol) VALUES (0)
> INSERT INTO BitTest (BitCol) VALUES (0)
> INSERT INTO BitTest (BitCol) VALUES (1)
> INSERT INTO BitTest (BitCol) VALUES (1)
> INSERT INTO BitTest (BitCol) VALUES (0)
> INSERT INTO BitTest (BitCol) VALUES (1)
> INSERT INTO BitTest (BitCol) VALUES (0)
> go
> -- Searched query - uses index s on x_bit
> SELECT * FROM BitTest WHERE BitCol = CAST(1 AS bit)
> -- Query w/o WHERE - uses index scan on x_bit
> SELECT * FROM BitTest
> go
> DROP TABLE BitTest
> go
> Here's the version of SQL Server I tested this on:
> SELECT @.@.Version
> go
> Microsoft SQL Server 2000 - 8.00.2187 (Intel X86)
> Mar 9 2006 11:38:51
> Copyright (c) 1988-2003 Microsoft Corporation
> Developer Edition on Windows NT 5.1 (Build 2600: Service Pack 2)
> --
> Hugo Kornelis, SQL Server MVP|||> That said, would it be preferable to put the bit col as the last column in
> the index, after EndDate? Where EndDate will be more selective than
> isCancelled?
Possibly. Remember that statistics is only kept for the first column in the
index. So if you have:
WHERE bitcol = 1
AND othercol = 2786
Then SQL Server doesn't know the selectivity for the "othercol = 2768" condi
tion, and because of
that the cost estimation can be off. Having othercol as the first column in
the index mean
statistics is available for that column and selectivity for othercol = 2786
can be determined.
However, if the index is defined over (othercol, bitcol) and you have anothe
r query:
WHERE bitcol = 1
Then SQL Server cannot use that index, as bitcol isn't the first column in t
hat index.
Tradeoffs...
Tibor Karaszi, SQL Server MVP
http://www.karaszi.com/sqlserver/default.asp
http://www.solidqualitylearning.com/
"Jim Underwood" <james.underwoodATfallonclinic.com> wrote in message
news:ecQcasviGHA.4504@.TK2MSFTNGP03.phx.gbl...
> Hugo,
> Thanks for that example. The results were identical on my installation.
> I was misled by this quote from BOL.
> bit
> Integer data type 1, 0, or NULL.
> Remarks
> Columns of type bit cannot have indexes on them.
> That will teach me to take BOL for granted without testing first.
> That said, would it be preferable to put the bit col as the last column in
> the index, after EndDate? Where EndDate will be more selective than
> isCancelled? Unless, of course, isCancelled has very few values of 0.
>
> "Hugo Kornelis" <hugo@.perFact.REMOVETHIS.info.INVALID> wrote in message
> news:tqfe82p289pqt02752cshltfhaoroubl4n@.
4ax.com...
> it
>|||Actually, my thought process was a little different, let me try to explain.
I may be way off here, but this is how I thought multicolumn indexes
worked...
We query for (yes, I realize this is different from the OP) :
TerritoryID = @.TerritoryID
AND EndDate = @.EndDate
AND IsCancelled = 0
Lets say we have 1,000,000 rows of data, and we have an index on
(TerritoryID, IsCancelled, EndDate)
@.TerritoryID narrows the search to 100 records
IsCancelled = 0 cuts that in half to 50 records
@.EndDate narrows those 50 records to 5 records
Now, lets say we have an index on (TerritoryID, EndDate, IsCancelled)
@.TerritoryID narrows the search to 100 records
@.EndDate narrows those 100 records to 10 records
IsCancelled = 0 cuts that in half to 5 records
In the case above wouldn't it be more efficient to have the date as the
second column in the index? Essentially, put the most selective column
before the others in the index. Of course, this assumes that SQL Server's
algorithms use the physical order of the columns to filter data, which may
not be the case.
Upon reviewing the query in the OP, it occurs to me that EndDate <= GetDate
may actually be less selective than IsCancelled = 0, and that for that
specific query having the bit column precede the date may be more efficient
after all.
"Tibor Karaszi" <tibor_please.no.email_karaszi@.hotmail.nomail.com> wrote in
message news:OS58CwviGHA.1600@.TK2MSFTNGP04.phx.gbl...
in
> Possibly. Remember that statistics is only kept for the first column in
the index. So if you have:
> WHERE bitcol = 1
> AND othercol = 2786
> Then SQL Server doesn't know the selectivity for the "othercol = 2768"
condition, and because of
> that the cost estimation can be off. Having othercol as the first column
in the index mean
> statistics is available for that column and selectivity for othercol =
2786 can be determined.
> However, if the index is defined over (othercol, bitcol) and you have
another query:
> WHERE bitcol = 1
> Then SQL Server cannot use that index, as bitcol isn't the first column in
that index.
> Tradeoffs...
> --
> Tibor Karaszi, SQL Server MVP
> http://www.karaszi.com/sqlserver/default.asp
> http://www.solidqualitylearning.com/
>
> "Jim Underwood" <james.underwoodATfallonclinic.com> wrote in message
> news:ecQcasviGHA.4504@.TK2MSFTNGP03.phx.gbl...
in
allow
>

Monday, March 26, 2012

Index question

I have the following index:
CREATE UNIQUE INDEX [MYINDEX1] ON [dbo].[LOGIN_TABLE]([Loginid],
logindate]) ON [PRIMARY]
GO
Do I still need to create the following index ?
CREATE INDEX [MYINDEX2] ON [dbo].[LOGIN_TABLE]([Loginid]) ON [PRIMARY]
GO
Thanks for any feedback........
DXC,
SQL Server stores statistics for the more left column in the key. This index
could be used for logic expressions referencing [Loginid] or ([Loginid] and
[logindate]). If you create the second index, may be SQL Server can decide to
use it because the key is shorter than the first one, so more rows can fit in
a page and less IO operations will be required.
Try some "select" statements with just the first index. If you are ok with
the response time and execution plan selected by SQL Server then do not
create the second one. Remember, indexes help sql server to find the data
faster, but also put more load for insert, delete, and update operations.
AMB
"DXC" wrote:

> I have the following index:
> CREATE UNIQUE INDEX [MYINDEX1] ON [dbo].[LOGIN_TABLE]([Loginid],
> logindate]) ON [PRIMARY]
> GO
> Do I still need to create the following index ?
>
> CREATE INDEX [MYINDEX2] ON [dbo].[LOGIN_TABLE]([Loginid]) ON [PRIMARY]
> GO
>
> Thanks for any feedback........
|||No. MYINDEX2 is redundant. SQL Server can use MYINDEX1 if it needs to seek
on Loginid
"DXC" <DXC@.discussions.microsoft.com> wrote in message
news:34A7F75B-5178-4DD1-BD31-AFEE69C13458@.microsoft.com...
>I have the following index:
> CREATE UNIQUE INDEX [MYINDEX1] ON [dbo].[LOGIN_TABLE]([Loginid],
> logindate]) ON [PRIMARY]
> GO
> Do I still need to create the following index ?
>
> CREATE INDEX [MYINDEX2] ON [dbo].[LOGIN_TABLE]([Loginid]) ON [PRIMARY]
> GO
>
> Thanks for any feedback........
|||That's what I thought............Thanks.
"Paul Wehland" wrote:

> No. MYINDEX2 is redundant. SQL Server can use MYINDEX1 if it needs to seek
> on Loginid
>
> "DXC" <DXC@.discussions.microsoft.com> wrote in message
> news:34A7F75B-5178-4DD1-BD31-AFEE69C13458@.microsoft.com...
>
>

Friday, March 23, 2012

Index question

I have the following index:
CREATE UNIQUE INDEX [MYINDEX1] ON [dbo].[LOGIN_TABLE]([Loginid],
logindate]) ON [PRIMARY]
GO
Do I still need to create the following index ?
CREATE INDEX [MYINDEX2] ON [dbo].[LOGIN_TABLE]([Loginid]) ON [PRIMARY]
GO
Thanks for any feedback........DXC,
SQL Server stores statistics for the more left column in the key. This index
could be used for logic expressions referencing [Loginid] or ([Loginid] and
[logindate]). If you create the second index, may be SQL Server can decide to
use it because the key is shorter than the first one, so more rows can fit in
a page and less IO operations will be required.
Try some "select" statements with just the first index. If you are ok with
the response time and execution plan selected by SQL Server then do not
create the second one. Remember, indexes help sql server to find the data
faster, but also put more load for insert, delete, and update operations.
AMB
"DXC" wrote:
> I have the following index:
> CREATE UNIQUE INDEX [MYINDEX1] ON [dbo].[LOGIN_TABLE]([Loginid],
> logindate]) ON [PRIMARY]
> GO
> Do I still need to create the following index ?
>
> CREATE INDEX [MYINDEX2] ON [dbo].[LOGIN_TABLE]([Loginid]) ON [PRIMARY]
> GO
>
> Thanks for any feedback........|||No. MYINDEX2 is redundant. SQL Server can use MYINDEX1 if it needs to seek
on Loginid
"DXC" <DXC@.discussions.microsoft.com> wrote in message
news:34A7F75B-5178-4DD1-BD31-AFEE69C13458@.microsoft.com...
>I have the following index:
> CREATE UNIQUE INDEX [MYINDEX1] ON [dbo].[LOGIN_TABLE]([Loginid],
> logindate]) ON [PRIMARY]
> GO
> Do I still need to create the following index ?
>
> CREATE INDEX [MYINDEX2] ON [dbo].[LOGIN_TABLE]([Loginid]) ON [PRIMARY]
> GO
>
> Thanks for any feedback........|||That's what I thought............Thanks.
"Paul Wehland" wrote:
> No. MYINDEX2 is redundant. SQL Server can use MYINDEX1 if it needs to seek
> on Loginid
>
> "DXC" <DXC@.discussions.microsoft.com> wrote in message
> news:34A7F75B-5178-4DD1-BD31-AFEE69C13458@.microsoft.com...
> >I have the following index:
> >
> > CREATE UNIQUE INDEX [MYINDEX1] ON [dbo].[LOGIN_TABLE]([Loginid],
> > logindate]) ON [PRIMARY]
> > GO
> >
> > Do I still need to create the following index ?
> >
> >
> > CREATE INDEX [MYINDEX2] ON [dbo].[LOGIN_TABLE]([Loginid]) ON [PRIMARY]
> > GO
> >
> >
> > Thanks for any feedback........
>
>sql

Monday, March 12, 2012

index hints on deletes

Can I not use index hints on delete statements as below ? Using SQL 2005
delete
from dbo.table1 WITH (index(idx_test))
where col1 <= 5
Are you getting an error? If so it would be nice to know what.
Andrew J. Kelly SQL MVP
Solid Quality Mentors
"Hassan" <hassan@.test.com> wrote in message
news:udtwNEjUIHA.5404@.TK2MSFTNGP06.phx.gbl...
> Can I not use index hints on delete statements as below ? Using SQL 2005
> delete from dbo.table1 WITH (index(idx_test))
> where col1 <= 5
|||Msg 1069, Level 15, State 1, Line 3
Index hints are only allowed in a FROM clause.
"Andrew J. Kelly" <sqlmvpnooospam@.shadhawk.com> wrote in message
news:uhAqFXjUIHA.3400@.TK2MSFTNGP03.phx.gbl...
> Are you getting an error? If so it would be nice to know what.
> --
> Andrew J. Kelly SQL MVP
> Solid Quality Mentors
>
> "Hassan" <hassan@.test.com> wrote in message
> news:udtwNEjUIHA.5404@.TK2MSFTNGP06.phx.gbl...
>
|||How about this:
delete a
from dbo.table1 AS a WITH (index(idx_test))
where a.col1 <= 5
Andrew J. Kelly SQL MVP
Solid Quality Mentors
"Hassan" <hassan@.test.com> wrote in message
news:OdKr5ujUIHA.4280@.TK2MSFTNGP06.phx.gbl...
> Msg 1069, Level 15, State 1, Line 3
> Index hints are only allowed in a FROM clause.
> "Andrew J. Kelly" <sqlmvpnooospam@.shadhawk.com> wrote in message
> news:uhAqFXjUIHA.3400@.TK2MSFTNGP03.phx.gbl...
>
|||or just
DELETE table1 from table1 with(index(idx_test))
WHERE col <= 5
But as far as I can tell from the BOL syntax description, the original
DELETE statement is perfectly legal. Is this some kind of bug?
Linchi
"Andrew J. Kelly" wrote:

> How about this:
> delete a
> from dbo.table1 AS a WITH (index(idx_test))
> where a.col1 <= 5
> --
> Andrew J. Kelly SQL MVP
> Solid Quality Mentors
>
> "Hassan" <hassan@.test.com> wrote in message
> news:OdKr5ujUIHA.4280@.TK2MSFTNGP06.phx.gbl...
>
|||What I'm reading is that DELETE only takes hints from a limited list
<table_hint_limited> and index hints are not in that list.
HTH
Kalen Delaney, SQL Server MVP
www.InsideSQLServer.com
http://blog.kalendelaney.com
"Linchi Shea" <LinchiShea@.discussions.microsoft.com> wrote in message
news:3E750688-DD9F-4567-BD65-515160B60119@.microsoft.com...[vbcol=seagreen]
> or just
> DELETE table1 from table1 with(index(idx_test))
> WHERE col <= 5
> But as far as I can tell from the BOL syntax description, the original
> DELETE statement is perfectly legal. Is this some kind of bug?
> Linchi
> "Andrew J. Kelly" wrote:

index hints on deletes

Can I not use index hints on delete statements as below ? Using SQL 2005
delete
from dbo.table1 WITH (index(idx_test))
where col1 <= 5Are you getting an error? If so it would be nice to know what.
--
Andrew J. Kelly SQL MVP
Solid Quality Mentors
"Hassan" <hassan@.test.com> wrote in message
news:udtwNEjUIHA.5404@.TK2MSFTNGP06.phx.gbl...
> Can I not use index hints on delete statements as below ? Using SQL 2005
> delete from dbo.table1 WITH (index(idx_test))
> where col1 <= 5|||Msg 1069, Level 15, State 1, Line 3
Index hints are only allowed in a FROM clause.
"Andrew J. Kelly" <sqlmvpnooospam@.shadhawk.com> wrote in message
news:uhAqFXjUIHA.3400@.TK2MSFTNGP03.phx.gbl...
> Are you getting an error? If so it would be nice to know what.
> --
> Andrew J. Kelly SQL MVP
> Solid Quality Mentors
>
> "Hassan" <hassan@.test.com> wrote in message
> news:udtwNEjUIHA.5404@.TK2MSFTNGP06.phx.gbl...
>> Can I not use index hints on delete statements as below ? Using SQL 2005
>> delete from dbo.table1 WITH (index(idx_test))
>> where col1 <= 5
>|||How about this:
delete a
from dbo.table1 AS a WITH (index(idx_test))
where a.col1 <= 5
--
Andrew J. Kelly SQL MVP
Solid Quality Mentors
"Hassan" <hassan@.test.com> wrote in message
news:OdKr5ujUIHA.4280@.TK2MSFTNGP06.phx.gbl...
> Msg 1069, Level 15, State 1, Line 3
> Index hints are only allowed in a FROM clause.
> "Andrew J. Kelly" <sqlmvpnooospam@.shadhawk.com> wrote in message
> news:uhAqFXjUIHA.3400@.TK2MSFTNGP03.phx.gbl...
>> Are you getting an error? If so it would be nice to know what.
>> --
>> Andrew J. Kelly SQL MVP
>> Solid Quality Mentors
>>
>> "Hassan" <hassan@.test.com> wrote in message
>> news:udtwNEjUIHA.5404@.TK2MSFTNGP06.phx.gbl...
>> Can I not use index hints on delete statements as below ? Using SQL 2005
>> delete from dbo.table1 WITH (index(idx_test))
>> where col1 <= 5
>|||or just
DELETE table1 from table1 with(index(idx_test))
WHERE col <= 5
But as far as I can tell from the BOL syntax description, the original
DELETE statement is perfectly legal. Is this some kind of bug?
Linchi
"Andrew J. Kelly" wrote:
> How about this:
> delete a
> from dbo.table1 AS a WITH (index(idx_test))
> where a.col1 <= 5
> --
> Andrew J. Kelly SQL MVP
> Solid Quality Mentors
>
> "Hassan" <hassan@.test.com> wrote in message
> news:OdKr5ujUIHA.4280@.TK2MSFTNGP06.phx.gbl...
> > Msg 1069, Level 15, State 1, Line 3
> > Index hints are only allowed in a FROM clause.
> >
> > "Andrew J. Kelly" <sqlmvpnooospam@.shadhawk.com> wrote in message
> > news:uhAqFXjUIHA.3400@.TK2MSFTNGP03.phx.gbl...
> >> Are you getting an error? If so it would be nice to know what.
> >>
> >> --
> >> Andrew J. Kelly SQL MVP
> >> Solid Quality Mentors
> >>
> >>
> >> "Hassan" <hassan@.test.com> wrote in message
> >> news:udtwNEjUIHA.5404@.TK2MSFTNGP06.phx.gbl...
> >> Can I not use index hints on delete statements as below ? Using SQL 2005
> >>
> >> delete from dbo.table1 WITH (index(idx_test))
> >> where col1 <= 5
> >>
> >
>|||What I'm reading is that DELETE only takes hints from a limited list
<table_hint_limited> and index hints are not in that list.
--
HTH
Kalen Delaney, SQL Server MVP
www.InsideSQLServer.com
http://blog.kalendelaney.com
"Linchi Shea" <LinchiShea@.discussions.microsoft.com> wrote in message
news:3E750688-DD9F-4567-BD65-515160B60119@.microsoft.com...
> or just
> DELETE table1 from table1 with(index(idx_test))
> WHERE col <= 5
> But as far as I can tell from the BOL syntax description, the original
> DELETE statement is perfectly legal. Is this some kind of bug?
> Linchi
> "Andrew J. Kelly" wrote:
>> How about this:
>> delete a
>> from dbo.table1 AS a WITH (index(idx_test))
>> where a.col1 <= 5
>> --
>> Andrew J. Kelly SQL MVP
>> Solid Quality Mentors
>>
>> "Hassan" <hassan@.test.com> wrote in message
>> news:OdKr5ujUIHA.4280@.TK2MSFTNGP06.phx.gbl...
>> > Msg 1069, Level 15, State 1, Line 3
>> > Index hints are only allowed in a FROM clause.
>> >
>> > "Andrew J. Kelly" <sqlmvpnooospam@.shadhawk.com> wrote in message
>> > news:uhAqFXjUIHA.3400@.TK2MSFTNGP03.phx.gbl...
>> >> Are you getting an error? If so it would be nice to know what.
>> >>
>> >> --
>> >> Andrew J. Kelly SQL MVP
>> >> Solid Quality Mentors
>> >>
>> >>
>> >> "Hassan" <hassan@.test.com> wrote in message
>> >> news:udtwNEjUIHA.5404@.TK2MSFTNGP06.phx.gbl...
>> >> Can I not use index hints on delete statements as below ? Using SQL
>> >> 2005
>> >>
>> >> delete from dbo.table1 WITH (index(idx_test))
>> >> where col1 <= 5
>> >>
>> >
>>

Index hint in delete statement?

According to what I see in BOL, the following should work:

delete

from dbo.tbl1 WITH (INDEX(idx_un01))

where tbl1_no = 1

Yet when I syntax check this I get:

Msg 1069, Level 15, State 1, Line 2

Index hints are only allowed in a FROM clause.

(Please ignore the fact that index hints are unnecessary / a bad idea / etc.)

What you wrote is the equivalent of:

delete

dbo.tbl1 WITH (INDEX(idx_un01))

where tbl1_no = 1

So really there's no FROM clause, and the error message returned is correct. If you're going to use a FROM clause, you need to specify what tables you're deleting from. i.e.:

delete dbo.tbl1

from dbo.tbl1 WITH (INDEX(idx_un01))

where tbl1_no = 1

In theory, you can join multiple tables in your FROM clause, which is why you need to indicate what table you want to delete.

|||

Hmmm. Interesting. What is even more interesting is that it accepts the WITH (ROWLOCK) hint without a quibble. I also don't see this syntax as being required in BOL. (It is only mentioned for joins / correlated subqueries.)

ref: ms-help://MS.SQLCC.v9/MS.SQLSVR.v9.en/tsqlref9/html/ed6b2105-0f35-408f-ba51-e36ade7ad5b2.htm

|||

The syntax is TSQL extension for UPDATE/DELETE statement. The ANSI SQL syntax for UPDATE and DELETE does not have a FROM clause at all. So there are two FROM clauses in the TSQL version of DELETE. I think it is a bug that we allow the locking hint and not the INDEX hint. IMO, both should be allowed without the FROM clause containing the table sources. You may want to file a bug at http://connect.microsoft.com. And both FROM clauses are optional also. See the DELETE statement topic in BOL where it is documented completely.

Generally speaking you should try to use the ANSI SQL syntax as far as possible and avoid using hints in most DML statements. The hint is just a hint and it can be overridden due to resource constraints for example. And by forcing certain indexes you are restricting the plan choices for the query optimizer also. Is there any specific reason why you want to use the hint in the DELETE statement? Are you having some wrong plan choices for the DELETE statement? If so, that might be a bug and it will be good if you can post a repro for that.

Index hell again.

Would you allow an index on Customer
CREATE NONCLUSTERED INDEX [IX_Customer] ON [dbo].[Customer]
(
[first_name] ASC,
[last_name] ASC,
[email] ASC
) ON [PRIMARY]
So the defrag on this is terrible and insertion on the batches is slowed
down.As always, it depends. I would certainly put a fill factor < 100 - and this
depends on how frequent your inserts and defrags are. This index would
cover a query such as:
select
email
from
Customer
where
first_name = 'John'
and last_name = 'Smith'
If you're using SQL 2005, you could make email an included column and just
key on first_name, last_name.
--
Tom
----
Thomas A. Moreau, BSc, PhD, MCSE, MCDBA
SQL Server MVP
Toronto, ON Canada
.
"_Stephen" <srussell@.electracash.com> wrote in message
news:%23rWVJ1wYGHA.5012@.TK2MSFTNGP04.phx.gbl...
Would you allow an index on Customer
CREATE NONCLUSTERED INDEX [IX_Customer] ON [dbo].[Customer]
(
[first_name] ASC,
[last_name] ASC,
[email] ASC
) ON [PRIMARY]
So the defrag on this is terrible and insertion on the batches is slowed
down.

Wednesday, March 7, 2012

Index Discussion

Hi Folks,

Got a topic open for debate.

We currently have an archive table - DDL

CREATE TABLE [dbo].[Audit] (
[id] [int] identity (1,1) NOT NULL ,
[col1] [char] (10) NOT NULL ,
[col2] [char] (15) NOT NULL ,
[col3] [int] NOT NULL ,
[col4] [varchar] (50) NOT NULL ,
[col5] [datetime] NOT NULL ,
[col6] [varchar] (4000) NULL ,
[col7] [char] (3) NULL
)
GO

This table grows to about 40 million rows during the course of the month. The table has a clustered index on the id field and a non clustered index on the col2 and col3. The id column is not used in queries. At the moment we run weekly dbcc reindexes on all the indexes. We are running into a space issue on the reindex of the clustered index (copying the whole table out , ordering etc) and are considering dropping the index or changing to a non clustered index. (The DBCC utility that we have built will only rebuilt all the indexes or none at all.)

I feel this is not a good idea and know my reasons. I would like some input as to why this might prove a bad idea.

Will it increase page splitting? Will the table performance be impacted even if the queries are not specifically using the clustered index?

What are the reasons for and against?

Thanks FolksWhy do yuo have an [id] column if you don't use it?

I am IDENTITY, there for I am....

Drop the Index

The when people start screaming, the create a non unique index...|||The when people start screaming, the create a non unique index...:D :D ... they don't scream... simply blame SQL server with no cause.:mad:|||I never designed the schema. Bag of pish if you ask me.

Nevertheless before I drop the index :

Will the table start to split pages if we lose the clustered ?

The table is inserted into the by date order. There is no index on the datatime field but the id field clustered index maintains the date order of the table. Would go if the clustered index was dropped?

Do the other non-clustered indexes not use the clustered as a backbone? Will the non-clustered grow if the clustered was dropped?

Am basing my concerns over dropping this index mainly from the advice on the link below.

http://www.sql-server-performance.com/clustered_indexes.asp

More conjecture please.|||OK, first, the order of data in a database has no meaning...

Second, (and I should have said this earlier), do NO alteration in a prod environment until you tested ANY approach in DEV

Me telling you to (and off the cuff) to just drop the index was so bad, I had to drink many margaritas to forget it...

Well, ok, I'm always looking for an excuse...

And no, indexes are not dependant on each other...

And keeping an IDENTITY to make sure the dates are in the right order (did I read that right) doesn't make sense to me...

The big question is...

CREATE TABLE with clustered index

Data is meant to be stored in that order...however data will be put on pages where it finds room...how much free space?

When the table is REORG'ed it will order the data by it...

Now the question...you drop a cluster, and then reorg...what happens?

Don't know, I'll have to test it...

However, I think you have bigger issues...|||You know what? I wanted to do the following, and then reorg the data pages...(it's a db2 term I guess), and realized I don't know how, except to unload and load (OK, another db2 term, bcp out and bcp in)...

Anyone?

I've DBCC REINDEX, but it doesn't mention anything about the pages...

got to be a way...

USE Northwind
GO

CREATE TABLE myTable99 (
Col1 int NOT NULL
, Col2 char(1) NOT NULL
)
GO

CREATE UNIQUE CLUSTERED INDEX myTable99_IX1 ON myTable99(Col1)
CREATE INDEX myTable99_IX2 ON myTable99(Col2)
GO

sp_help myTable99
GO

INSERT INTO myTable99(Col1, Col2)
SELECT 1, 'A' UNION ALL
SELECT 2, 'B' UNION ALL
SELECT 3, 'C' UNION ALL
SELECT 4, 'D'
GO

SELECT * FROM myTable99
GO

DROP INDEX myTable99.myTable99_IX1
GO

sp_help myTable99
GO

INSERT INTO myTable99(Col1, Col2)
SELECT 5, 'E' UNION ALL
SELECT 6, 'F' UNION ALL
SELECT 7, 'G' UNION ALL
SELECT 8, 'H'
GO

SELECT * FROM myTable99
GO|||Thanks for the feedback Brett,

Don't worry - Would never drop an index on a table in prod without fully testing and understanding the implications before doing so

Hence this thread...

Going to some testing and get back to you.

Is there a way in T-SQL you can check the size of a specific index?

Don't trust EM ....|||Originally posted by aldo_2003
Don't trust EM ....

Good...

Of a specific index?

Anyone...

sp_spaceused myTable99
GO

Will tell you the size of all...

I'll keep looking...

EDIT: IF this was DB2 I'd have an answer...|||sysindexes tells you how many pages where used

can we simply multiply this by 8kb to get the answer?|||ANytime to get accurate sizes better to DBCC UPDATEUSAGE or use @.UPDATEUSAGE='TRUE' in SP_SPACEUSED statements.|||Brett, Satya ,

Have done a bit of testing

Inserted 6 million rows into this table with all the indexes
i.e 1 clustered and 2 non clustered

Did sp_spaceused with DBCC UPDATEUSAGE
index size = 233278kb

Then i dropped the clustered index

Did sp_spaceused with DBCC UPDATEUSAGE

index size = 284104kb

Why has the total index size gone up when I have dropped the an index?

What is going on ??

"And no, indexes are not dependant on each other..."?

Anybody ?|||Have you performed DBCC DBREINDEX before and after CLustered Index drop?

I've bit doubt in this regard after this it should return correct sizes.|||Have done this and tested

Still get the same result -

i.e increse in overall index size when I drop the clustered index

has anyone else noticed this behaviour or am I the only one.

shame SQL Server has no T-SQL to check out the size of specific indexes|||Thats for sure there is no direct deal to get the result.
http://www.sql-server-performance.com/q&a13.asp - review for information.

HTH|||Thanks Satya,

Still don't know what is happening with my indexes though|||Index internals. I still wish I had a chance to get to that lecture when it was around last, but here is what I do know.

A clustered index is an index that has the data pages as its leaf pages. In otherwords, this is the order in which the data is supposed to be stored on disk. With extent switches, and pages from other indexes peppered in, the data may not be contiguous, but the theory is there. The beauty of a clustered index is that if you are expecting ranges of data to be scanned, the data is all in a nice row on the disk to be scooped up. The bad side is that if you are planting data in the table in a random order, you end up with all sorts of page splits. This is why clustered indexes on Identity columns became all the rage.

You may remember that Microsoft suggests that you make the clustered key as small as possible, as well. With just the above reasons, there is no justification for this, so there is a second reason. Any non-clustered index will use the clustered index key in place of the rowid, if a clustered index exists. This means that a generic record for a non-clustered index looks like this:

indexed column1, indexed column2..., indexed columnn:clustered index column1, clustered index column2,...clustered index columnn

When you have an integer as the sole clustered index key, the second part of the non-clustered index row is quite small (4 bytes), but if you substitute a rowid (I think a rowid is fileid:pageid:slot number), then you have increased the size of the individual records in the index.

Clear as mud?

Now, the question becomes, are you running queries on the archive table?|||Excellent Answer MCrowley

So non clustered indexes do use clustered indexes to assist there own structure.

We do run queries against the archive table but performance is not a key factor. Non OLTP type enviroment.

What is an issue is the space and especially the space when a rebuild of the clustered index occurs.

I'm going to take some of the queries run by our users into our dev enviroment and make sure that the server does not freak out when I run the same queries after dropping the clustered index.

Thanks to all whom have helped me out on this.
Learned quite a bit about indexes this week - time for a bevy ...!|||One last thing I forgot to mention. I believe that when you run dbcc dbreindex against a clustered index, the whole table (i.e. the leaf nodes of the clustered index) is copied to a new location. So effectively you need to have as much free space in the database as the table takes up, in order to be successful. DBCC DBREINDEX against a clustered index (or just run against the table name) also has the unfortunate side effect of rebuilding all of the non-clustered indexes, too, so you have to add that space on, too. DBCC INDEXDEFRAG is not as effective as DBREINDEX, but it is nicer to the system.|||Thanks again

Lets hope future versions of SQL make easier for DBA's to size all objects (i.e specific indexes) in the databases with the ability to attribute the overall size of the database to the sum of the objects within it.

All the best.|||Testing at my end proves to be working in terms of sizes what you're looking for.

For instance with clustered index presence database free space was 2.4gigs and after removal it was 2.8gigs.

I will explain more about this on Monday.:cool:|||From BOL:

Nonclustered indexes can be defined on a table with a clustered index, a heap, or an indexed view. In Microsoft SQL Server 2000, the row locators in nonclustered index rows have two forms:

If the table is a heap (does not have a clustered index), the row locator is a pointer to the row. The pointer is built from the file identifier (ID), page number, and number of the row on the page. The entire pointer is known as a Row ID.

If the table does have a clustered index, or the index is on an indexed view, the row locator is the clustered index key for the row. If the clustered index is not a unique index, SQL Server 2000 makes duplicate keys unique by adding an internally generated value. This value is not visible to users; it is used to make the key unique for use in nonclustered indexes. SQL Server retrieves the data row by searching the clustered index using the clustered index key stored in the leaf row of the nonclustered index.
Because nonclustered indexes store clustered index keys as their row locators, it is important to keep clustered index keys as small as possible. Do not choose large columns as the keys to clustered indexes if a table also has nonclustered indexes.|||I would also experiment with having col5, col2, and col3 as clustered index, and id as unique constraint against existing queries.|||The whole point is to save some space on server, so not in terms of performance perspective. By dropping the existing clustered index it can save 500megs atleast and by adding this composite clustered index it will addup more space.|||Originally posted by Satya
The whole point is to save some space on server, so not in terms of performance perspective. By dropping the existing clustered index it can save 500megs atleast and by adding this composite clustered index it will addup more space.

First, I said "experiment", second, - I was trying to combine the need for performance to be retained while trying to eliminate the need for reindexing on a weekly basis by structuring the clustered index in such a way that reindexing will not be needed. And I think this approach will work better than dropping the index while still starving for space maybe in a couple of weeks due to increase in data (my 2 cents)|||Originally posted by rdjabarov
First, I said "experiment", second, - I was trying to combine the need for performance to be retained while trying to eliminate the need for reindexing on a weekly basis by structuring the clustered index in such a way that reindexing will not be needed. And I think this approach will work better than dropping the index while still starving for space maybe in a couple of weeks due to increase in data (my 2 cents)
No worries mate, just hurl thru.

Sunday, February 19, 2012

INDEX and VIEWS

Hi all,
Let say that I have a table Customer
CREATE TABLE [dbo].[Customer] (
[CustomerId] [int] NOT NULL ,
[CustomerName] [nvarchar] (50),
[CustomerAge] [int] NOT NULL
) ON [PRIMARY]
GO
Let say I have an index on CustomerAge.
If I have a view defined as:
CREATE VIEW dbo.VIEWCustomer
AS
SELECT dbo.Customer.*
FROM dbo.Customer
and then if I execute the following SQL statement:
select * from VIEWCustomer where CustomerAge = 25
Will that statement use the index of the table Customer (on the field
CustomerAge) or will it not (because no index can be defined on a view)?
In other words, if a select on a view is using a WHERE clause for which
there is an index defined for the table.field defined in the view, will it
be used or not?
Best regards,
Francois MalgreveYou can check this yourself by examining the execution plan in Query
Analyzer. The indexes certainly can be used when referencing a view in
just the same way as they are with tables.
David Portas
SQL Server MVP
--