January 15, 2013 at 10:43 am
Hello...
I'm a beginner in Indexing
I've table as following,
CREATE TABLE [dbo].[tbl_Penyata](
[idx] [int] IDENTITY(-2147483648,1) NOT NULL,
[nogaji] [char](6) NOT NULL,
[TkhTransaksi] [date] NOT NULL,
[NoSiri] [varchar](6) NULL,
[kodBank] [char](6) NOT NULL,
[AkaunBank] [varchar](16) NOT NULL,
[singkatan_bank] [nvarchar](10) NULL,
[AktPst] [char](4) NOT NULL,
[edtype] [char](2) NOT NULL,
[edcode] [char](4) NOT NULL,
[eln_payslip] [varchar](30) NULL,
[edAmount] [decimal](10, 2) NOT NULL,
CONSTRAINT [pk_tbl_penyata] PRIMARY KEY CLUSTERED
(
[idx] ASC,
[nogaji] ASC,
[TkhTransaksi] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS =
ON, ALLOW_PAGE_LOCKS = ON) ON [ps_TkhTransaksi]([TkhTransaksi])
) ON [ps_TkhTransaksi]([TkhTransaksi])
tbl_Penyata using partitioned tables. This is the info
object_idTbNameindex_nameindex_type_descpartition_schemedata_space_idfunction_namefunction_id
1266103551tbl_Penyatadbo.tbl_Penyata_UQ1NONCLUSTEREDps_TkhTransaksi65601pf_TkhTransaksi65536
1266103551tbl_Penyatadbo.tbl_Penyata_UQ2NONCLUSTEREDps_TkhTransaksi65601pf_TkhTransaksi65536
1266103551tbl_Penyatadbo.tbl_Penyata_UQ3NONCLUSTEREDps_TkhTransaksi65601pf_TkhTransaksi65536
1266103551tbl_Penyatapk_tbl_penyataCLUSTEREDps_TkhTransaksi65601pf_TkhTransaksi65536
object_idTbNameindex_idpartition_numberrowsindex_nameindex_type_descdata_space_idFILEGROUP_NAMEfunction_idPf_Nametype_descboundary_value_on_rightdestination_data_space_idparameter_idvalue
1266103551tbl_Penyata11166296pk_tbl_penyataCLUSTERED65601PRIMARY65536pf_TkhTransaksiRANGE1112012-06-01 00:00:00.000
1266103551tbl_Penyata12337293pk_tbl_penyataCLUSTERED65601PRIMARY65536pf_TkhTransaksiRANGE1212012-12-01 00:00:00.000
1266103551tbl_Penyata13219018pk_tbl_penyataCLUSTERED65601PRIMARY65536pf_TkhTransaksiRANGE1312013-06-01 00:00:00.000
1266103551tbl_Penyata140pk_tbl_penyataCLUSTERED65601PRIMARY65536pf_TkhTransaksiRANGE1412013-12-01 00:00:00.000
1266103551tbl_Penyata150pk_tbl_penyataCLUSTERED65601PRIMARY65536pf_TkhTransaksiRANGE15NULLNULL
1266103551tbl_Penyata131166296dbo.tbl_Penyata_UQ1NONCLUSTERED65601PRIMARY65536pf_TkhTransaksiRANGE1112012-06-01 00:00:00.000
1266103551tbl_Penyata132337293dbo.tbl_Penyata_UQ1NONCLUSTERED65601PRIMARY65536pf_TkhTransaksiRANGE1212012-12-01 00:00:00.000
1266103551tbl_Penyata133219018dbo.tbl_Penyata_UQ1NONCLUSTERED65601PRIMARY65536pf_TkhTransaksiRANGE1312013-06-01 00:00:00.000
1266103551tbl_Penyata1340dbo.tbl_Penyata_UQ1NONCLUSTERED65601PRIMARY65536pf_TkhTransaksiRANGE1412013-12-01 00:00:00.000
1266103551tbl_Penyata1350dbo.tbl_Penyata_UQ1NONCLUSTERED65601PRIMARY65536pf_TkhTransaksiRANGE15NULLNULL
1266103551tbl_Penyata141166296dbo.tbl_Penyata_UQ2NONCLUSTERED65601PRIMARY65536pf_TkhTransaksiRANGE1112012-06-01 00:00:00.000
1266103551tbl_Penyata142337293dbo.tbl_Penyata_UQ2NONCLUSTERED65601PRIMARY65536pf_TkhTransaksiRANGE1212012-12-01 00:00:00.000
1266103551tbl_Penyata143219018dbo.tbl_Penyata_UQ2NONCLUSTERED65601PRIMARY65536pf_TkhTransaksiRANGE1312013-06-01 00:00:00.000
1266103551tbl_Penyata1440dbo.tbl_Penyata_UQ2NONCLUSTERED65601PRIMARY65536pf_TkhTransaksiRANGE1412013-12-01 00:00:00.000
1266103551tbl_Penyata1450dbo.tbl_Penyata_UQ2NONCLUSTERED65601PRIMARY65536pf_TkhTransaksiRANGE15NULLNULL
1266103551tbl_Penyata151166296dbo.tbl_Penyata_UQ3NONCLUSTERED65601PRIMARY65536pf_TkhTransaksiRANGE1112012-06-01 00:00:00.000
1266103551tbl_Penyata152337293dbo.tbl_Penyata_UQ3NONCLUSTERED65601PRIMARY65536pf_TkhTransaksiRANGE1212012-12-01 00:00:00.000
1266103551tbl_Penyata153219018dbo.tbl_Penyata_UQ3NONCLUSTERED65601PRIMARY65536pf_TkhTransaksiRANGE1312013-06-01 00:00:00.000
1266103551tbl_Penyata1540dbo.tbl_Penyata_UQ3NONCLUSTERED65601PRIMARY65536pf_TkhTransaksiRANGE1412013-12-01 00:00:00.000
1266103551tbl_Penyata1550dbo.tbl_Penyata_UQ3NONCLUSTERED65601PRIMARY65536pf_TkhTransaksiRANGE15NULLNULL
I execute SQL as following,
select
eln_payslip,
edamount
from dbo.tbl_Penyata
where nogaji='047911' and edtype='01' and edcode not in ('0157')
and DATEPART(YEAR,tkhtransaksi)=DATEPART(YEAR,'20121201')
and DATEPART(MONTH,tkhtransaksi)=DATEPART(MONTH,'20121201')
order by edcode
My Execution Plan as following,
Please guide me to add Indexes (if any)
January 15, 2013 at 10:57 am
Please post index definitions (they're not in your script) and execution plan (not the picture of it), as per http://www.sqlservercentral.com/articles/SQLServerCentral/66909/
Also, you can simplify that query as:
select
eln_payslip,
edamount
from dbo.tbl_Penyata
where nogaji='047911' and edtype='01' and edcode not in ('0157')
and tkhtransaksi >= '2012/12/01' and tkhtransaksi < DATEADD(mm,1,'2012/12/01')
order by edcode
That makes the date predicate SARGable and hence able to use an index seek, assuming you have an appropriate index.
Gail Shaw
Microsoft Certified Master: SQL Server, MVP, M.Sc (Comp Sci)
SQL In The Wild: Discussions on DB performance with occasional diversions into recoverability
January 15, 2013 at 11:06 am
GilaMonster (1/15/2013)
Please post index definitions (they're not in your script) and execution plan (not the picture of it), as per http://www.sqlservercentral.com/articles/SQLServerCentral/66909/Also, you can simplify that query as:
select
eln_payslip,
edamount
from dbo.tbl_Penyata
where nogaji='047911' and edtype='01' and edcode not in ('0157')
and tkhtransaksi >= '2012/12/01' and tkhtransaksi < DATEADD(mm,1,'2012/12/01')
order by edcode
That makes the date predicate SARGable and hence able to use an index seek, assuming you have an appropriate index.
Hi GilaMonster,
I attached my Execution Plan
January 15, 2013 at 11:31 am
Current index definitions please.
Gail Shaw
Microsoft Certified Master: SQL Server, MVP, M.Sc (Comp Sci)
SQL In The Wild: Discussions on DB performance with occasional diversions into recoverability
January 15, 2013 at 11:55 am
This is my Index so far
CREATE NONCLUSTERED INDEX [dbo.tbl_Penyata_IX1] ON [dbo].[tbl_Penyata]
(
[AktPst] ASC,
[edcode] ASC
)
INCLUDE ( [nogaji],
[TkhTransaksi],
[edAmount]) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
CREATE NONCLUSTERED INDEX [dbo.tbl_Penyata_IX2] ON [dbo].[tbl_Penyata]
(
[AktPst] ASC,
[edtype] ASC,
[edcode] ASC
)
INCLUDE ( [nogaji],
[TkhTransaksi],
[eln_payslip],
[edAmount]) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
CREATE NONCLUSTERED INDEX [dbo.tbl_Penyata_IX3] ON [dbo].[tbl_Penyata]
(
[AktPst] ASC,
[edtype] ASC,
[edcode] ASC
)
INCLUDE ( [nogaji],
[TkhTransaksi],
[eln_payslip],
[edAmount]) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
January 15, 2013 at 12:36 pm
You've got redundant indexes there. The 2nd and 3rd are identical, you should drop one of them.
For the revised query that I gave you, you probably want one of these, which I can't tell, you need to test, see which is more optimal
Index on (nogaji, edtype, tkhtransaksi ) Include (eln_payslip, edamount, edcode )
or
Index on (nogaji, edtype, edcode ) Include (eln_payslip, edamount, tkhtransaksi )
Gail Shaw
Microsoft Certified Master: SQL Server, MVP, M.Sc (Comp Sci)
SQL In The Wild: Discussions on DB performance with occasional diversions into recoverability
January 15, 2013 at 2:52 pm
tq mam
January 15, 2013 at 4:23 pm
Better yet, forget the dopey "cluster first by identity" and cluster the table the best way: that is THE most important thing for performance.
Based on what you've posted, it seems to be:
CONSTRAINT [pk_tbl_penyata] PRIMARY KEY CLUSTERED
([nogaji] ASC, [TkhTransaksi] ASC, [idx] ASC /*included to make the PK unique*/)
--<or>
--([TkhTransaksi] ASC, [nogaji] ASC, [idx] ASC /*included to make the PK unique*/)
and assuming that "nogaji" and "TkhTransaksi" are naturally ascending[/u].
If not, you have a choice to make:
-- if only TkhTransaksi is naturally ascending, but you specify it on (almost) all SELECTs, just make it the first column in the clustered index, as in the 2nd definition above;
-- if only nogaji is ascending, put it first;
-- if both naturally ascend, put whichever column you specify more often in SELECTs first in the key.
Then you won't need all those extra indexes, which force every DELETE, INSERT and UPDATE to occur mutliple times in multiple indexes, just to provide reasonable access time for (almost) every basic SELECT!
SQL DBA,SQL Server MVP(07, 08, 09) "It's a dog-eat-dog world, and I'm wearing Milk-Bone underwear." "Norm", on "Cheers". Also from "Cheers", from "Carla": "You need to know 3 things about Tortelli men: Tortelli men draw women like flies; Tortelli men treat women like flies; Tortelli men's brains are in their flies".
January 15, 2013 at 7:15 pm
First and most important thing to do is to choose a good clustering key.
Currently your CL key columns are also a primary key columns: idx, nogaji, TkhTransaksi
Your table is partitioned by date column: TkhTransaksi
Your NC (non-clustered) indexes are global, not partitioned (or you scripted them wrong?).
It would open some cool features for you if all indexes would be aligned, that is partitioned equally as CL index
instead of having non-partitioned, global indexes. One of the benefits would be partition switching and easier management.
Three-column CL key is wider than needed to be unique and ever-increasing.
Consider changing your CL index key to TkhTransaksi, idx.
Or, if TkhTransaksi is not ever-increasing and queries do not filter very often by TkhTransaksi column: idx, TkhTransaksi
I think better option would be the first one, but test how fast fragmentation grows and a define fill factor bit lower than 100 (e.g. 90-95%).
Depending on combined density of columns, those 3 NC indexes probably could be consolidated into just one index
with key columns: AktPst, edtype, edcode
and included columns: nogaji, TkhTransaksi, eln_payslip, edAmount
Could you post selectivity (1/number of distinct values) for columns: nogaji, edtype, and edcode?
Also combined density of (AktPst, edtype), (AktPst, edtype, edcode) and (AktPst, edcode) ?
If the most selective (the one with the most distinct values) is nogaji, then index with leading column nogaji as Gail suggested, would be good.
Also Gail's suggested change in your query not to use functions (DATEPART, etc) around key index columns is really very important for performance,
because if you do, index cannot be and will not be used at all in that query!
Viewing 9 posts - 1 through 8 (of 8 total)
You must be logged in to reply to this topic. Login to reply