Showing posts with label guys. Show all posts
Showing posts with label guys. Show all posts

Monday, March 26, 2012

Performance Question about: ExecStoredProcedure with ATL OLEDB Consumer Templates.

Hi Guys,

I need help in one fine tuning problem. I have developed one Datalayer that it have more implementations depedending on Database Server.

Our older implementation it is based on the db Library from Sql Server. And this implememtation we have replace it with an OLE DB ATL Consumer Templates implementation.

After comparing the performance of course and after we saw that the OLE DB ATL implementation faster is, we said it is a good decision. The compare i have made it with Microsoft SQL Server 2000 for both implementations.

But I forgot to test one statement and this was the Stored procedure exec statement.

All the other statement were faster with ATL OLE DB in compare with DB Library but the ExecStoredProcedure not, and I mean select, delete, update, insert and BCP insert are faster.

After making research why the OLE DB exec Stored Procedure call it is not faster I found the reason for: the OLE DB it is asking the SQL Server before running the store procedure the parameter structure( info like name, type, size etc ..).

If the stored procedure call it is fast (very fast - by example if i read only one row from one table based on a cluster index) then the overload for asking the parameter information it is too big in compare with db Library run time who it is not asking such information.

Lets say I have a stored procedure who it is reading from the database one book with a specific autoid.

So I would expect to run on a SQL Server side this statement:

exec di_sp_di_book_autoid @.autoid = 452

but starting the SQL Profiler I saw that instead of one statement the OLE DB it is sending 2 statements:

exec [demo_test]..sp_procedure_params_rowset N'di_sp_di_book_autoid', 1, NULL, NULL

exec di_sp_di_book_autoid @.autoid = 452,

First statement it is reading the information about the input and output parameters like type size and others... and after it runs the stored procedure only.

The ATL OLE DB it have a lot of properties that somebody can used them to control the behavior of different OLE DB Classes.

I've tried to find one property ( in OLEDB named Parameter) to deactivate this first call to win time and performance of course maybe loosind some error tolerance.

Here I attach the example code as Visual C++ Project example in Visual Studio 2003:

I describe how you can create such a project:

Create one Sample Project with just one Windows Dialog,

One this Dialog make 2 Buttons. In the first button event handler write this connection code:

void CSPTestDlg::OnButtonConnect()

{

USES_CONVERSION;

CWaitCursor waitCursor;

if (m_pDataSource = new CDataSource)

{

CString sServer = "DIKON_NT_005\\SQL2K";

CString sDatabase = "demo_oledb";

CString sUserId = "sqluser1";

CString sPassword = "***";

CDBPropSet dbinit[2] = {DBPROPSET_DBINIT, DBPROPSET_DATASOURCEINFO};

dbinit[0].AddProperty(DBPROP_INIT_DATASOURCE, sServer);

dbinit[0].AddProperty(DBPROP_INIT_CATALOG, sDatabase);

dbinit[0].AddProperty(DBPROP_AUTH_USERID, sUserId);

dbinit[0].AddProperty(DBPROP_AUTH_PASSWORD, sPassword);

dbinit[0].AddProperty(DBPROP_INIT_LCID, (long) 2057);

dbinit[0].AddProperty(DBPROP_INIT_PROMPT, (short) 4);

if (m_pDataSource->Open(_T("SQLOLEDB.1"), dbinit, 2) == S_OK)

{

_variant_t v;

HRESULT hr = m_pDataSource->GetProperty(DBPROPSET_DATASOURCEINFO, DBPROP_MULTIPLERESULTS, &v);

AtlTraceErrorRecords(hr);

if (m_pSession = new CSession)

{

if (m_pSession->Open(*m_pDataSource) == S_OK)

{

GetDlgItem(IDC_BUTTON_CONNECT)->EnableWindow(FALSE);

GetDlgItem(IDC_BUTTON_DISCONNECT)->EnableWindow(TRUE);

GetDlgItem(IDC_BUTTON_EXEC)->EnableWindow(TRUE);

return;

}

else {

MessageBox("Cannot open session!", NULL, MB_OK | MB_ICONERROR);

}

}

}

else {

CString sMessage;

sMessage.Format("Failed to connect to server '%s', database '%s'...", sServer, sDatabase);

MessageBox(sMessage, NULL, MB_OK | MB_ICONERROR);

}

}

delete m_pSession;

m_pSession = NULL;

delete m_pDataSource;

m_pDataSource = NULL;

return;

}

In the second button handler pls copy this code:

void CSPTestDlg::OnButtonExec()

{

DWORD dwStart = GetTickCount();

DWORD dwSum[3] = {0};

for (int nCount = 0; nCount < 10000; nCount++) {

DoTestManualAccessor();

}

DWORD dwEnd = GetTickCount();

DWORD dwTime = dwEnd - dwStart;

CString sMessage;

sMessage.Format("Time: %.3lf sec", dwTime / 1000.0);

MessageBox(sMessage);

return;

}

Here come in plus the code that truns in the second button :

void CSPTestDlg::DoTestManualAccessor()

{

CString sqlStatement;

sqlStatement = "{call di_sp_di_book_autoid(?)}";

CCommand<CManualAccessor, CRowset, CMultipleResults> cmd;

VARIANT v[nParameters];

for (int n = 0; n < nParameters; n++) {

VariantInit(& v[ n ]);

}

v[nParameters-1].vt = VT_I4;

v[nParameters-1].lVal = 15;

/*

CDBPropSet dbinit(DBPROPSET_ROWSET);

dbinit.AddProperty(DBPROP_SERVERCURSOR, true);

dbinit.AddProperty(DBPROP_IRowsetChange, false);

*/

HRESULT hr;

hr = cmd.Create(*m_pSession, sqlStatement);

//hr = cmd.Prepare();

hr = cmd.CreateParameterAccessor(nParameters, (void*) 0x01, 0);

char c_buf[4096] = {NULL};

wchar_t w_buf[4096] = {NULL};

cmd.AddParameterEntry(1, DBTYPE_VARIANT, sizeof(_variant_t), &v[0], NULL, NULL, DBPARAMIO_INPUT);

//(CDBPropSet*)&dbinit

//hr = cmd.Open((CDBPropSet*)&dbinit, NULL, false);

hr = cmd.Open(NULL, NULL,false);

AtlTraceErrorRecords(hr);

if (cmd.m_spRowset) {

cmd.CreateAccessor(3, (void*) 0xfefefefe, 0);

long id = 0;

cmd.AddBindEntry(1, DBTYPE_I4, sizeof(id), &id, NULL, NULL);

long ref = 0;

cmd.AddBindEntry(2, DBTYPE_I4, sizeof(ref), &ref, NULL, NULL);

char name[256] = {NULL};

cmd.AddBindEntry(3, DBTYPE_STR, sizeof(name), &name, NULL, NULL);

hr = cmd.Bind();

do

{

hr = cmd.MoveFirst();

while (hr == S_OK)

{

hr = cmd.MoveNext();

}

long out;

hr = cmd.GetNextResult(&out);

}

while (hr == S_OK);

}

for (int n = 0; n < nParameters; n++) {

VariantClear(& v[ n ]);

}

}

In the header file you must declare this 2 members:

CDataSource* m_pDataSource;

CSession* m_pSession;

In the Header File where the Dialog declared is you must include this fiels too:

#include "atldbcli.h"

#include "comutil.h"

#pragma comment(lib, "comsupp.lib")

Now the Project must run.First correct the login information of course for the connection on your MS SQL Server 2000.

Who wants to get the complete project pls give me your email adress and I will send you the complete Project.

Some comments about this very simple example are: I was commenting the Prepare call because instead of making the call faster it was making the call slower.

And I was trying to set with help of the class CDBPropSet some propertis to make the call faster.The same problem no succes with all porperties I have tried.

The question is it: is my code ok ?

Somebody knows any optimization that i can use ?

It is possible to deactivate this call for asking the parameter info that ATL OLE DB it is making automatically ?

Hi Vasile,

Try binding the parameter as something other than DBTYPE_VARIANT, e.g.

int a1 = 2;

cmd.AddParameterEntry(1, DBTYPE_I4, sizeof(a1), &a1, NULL, NULL, DBPARAMIO_INPUT);

I believe that binding as a variant causes oledb to go once to the server to figure out the actual data type the server is expecting. If the command is going to be executed repeatedly, this is not so bad since the server won't have to do the conversion - better to do that on the client, for the sake of scalability.

Note that if you execute the command in a loop, without destroying the CCommand object between iterations, the sp_procedure_params_rowset call is only done once.

- Dave

|||

Hi David,

I have tested your solution. It is working! Thanks a lot.

In the test program(release version) running the stored procedure 10000 times with the Variant bind it takes 15 seconds and with the int bind it takes 7.5 seconds.

So it takes double so much time with the Variant as with the int.The overload making the bind with the Variant it is to much I think. Maybe should be made clear in the documention form ATL Consumer Templates this costs, for who it is taking the decision to do the Variant bind instead of more type specific bind.

About the second idea it is good too. It is allready implemented but the problem it is I have a IConnection interface who it is having 2 object implementations with DB Library and with ATL OLE DB Consumer Templates. So everything it is encapsulated the client doesn't know what implementation it is using only one Object from our application it takes the responsability to choose and set the implementation.

I said this to know that we are not working directly with CCommand objects in the client code. The CCommand object in the OLEDBConnection I am not destroying it after every call but in general I am using not more then one call one after another from the same stored procedure(I am saving the last Store procedure name executed so if the next call it is made with the same stored procedure I don't need to make the initialization part but in general more then 99% from the use cases it is not helping because in the real case the execution of one store procedure it is followed by the execution of another stored procedure ).

Don't take the test application as I send it to you the real case. It is just a test program to isolate the execute store procedure implementation and to be able to test the performance and the behavior of OLE DB.

Your solution was helping me a lot. Thanks again!

Performance question

Good afternoon,

I'd like to know what you guys think about this performance question. In order to describe it well, I'll layout a simlpe table, and query, and I'll explain the question after that.

[Table: Categories]
Id [PK]
Alias NVarChar(50) [ASC Index]

[Stored Procedure Query]

SELECT C.IdAS Id,C.AliasAS CategoryFROMCategories CORDER BYC.AliasASC;

My question is simple. Let's supose we are getting a good sum of rows, like 10.000, to fill out a list. Even though that wouldn't be the best practice, because we should implement some sort of paging, we'll just ignore that fact for the sake of simplicity.

The question is: What would perform better? The query that I've writen above or a query that was exactly the same but instead of having Order By C.Alias ASC we would have Order BY Category ASC (being Category an alias created in the select statement)?

I know this might be seen as a dumb non-sense question... But still, I was just wondering if anyone knew the answer.

Best regards,
DBA

Hi,

the Index will do the job?

with proper indexing, the result will be noticible

with no index and ordering sorting will suffer

IMHO

Friday, March 23, 2012

Performance problems with query

Guys,
I'm stumped. While its not pertinent to the
matter, we are running a Vignette content management
system on Win2k with Sql 2000 Enterprise on a cluster.
The server has 2 Gig of RAM , 2 CPU's and the database
size is 1.5G.
The query below is fired at login. The indexes
seem fine based on the query plan. When I look through
profiler, the query below takes a very high # of CPU
cycles and reads. It consistently takes more than 1.5
seconds to execute the query below. I did a dbcc pintable
for ALL the tables in the query and that did not help
either. It seemed to make it worse (3 seconds and above)
Any idea what could be the issue here? The server
is not really heavily taxed.
The tables are small. They have very few rows.
VGNCCB_ROLE 939
VGNCCB_ROLE_JT 62389
VGNCCB_GROUP_USER_JT 1364
The problem Query:
select
ROLE_ID,
NAME,
DESCRIPTION,
CREATE_DATE,
MODIFIED_DATE
FROM
vign.VGNCCB_ROLE -- Clustered Indexed on Role ID
WHERE
ROLE_ID in
(select ROLE_ID
FROM
vign.VGNCCB_ROLE_JT -- Non clustered indexes
on USER_NAME AND non clustered on GROUP_ID
WHERE
USER_NAME = 'testRole' or GROUP_ID in (select
GROUP_ID
FROM
vign.VGNCCB_GROUP_USER_JT -- Non clustered
index on USER_NAME
WHERE
USER_NAME = 'testRole'))
I'd appreciate it if someone could follow me in this
thread to completion. Such a simple query should not take
this long.
TIA,
Jack
.See my reply to your previous post from this morning.
"Jack A" <anonymous@.discussions.microsoft.com> wrote in message
news:fc6001c43e8b$7d505750$a301280a@.phx.gbl...
> Guys,
> I'm stumped. While its not pertinent to the
> matter, we are running a Vignette content management
> system on Win2k with Sql 2000 Enterprise on a cluster.
> The server has 2 Gig of RAM , 2 CPU's and the database
> size is 1.5G.
> The query below is fired at login. The indexes
> seem fine based on the query plan. When I look through
> profiler, the query below takes a very high # of CPU
> cycles and reads. It consistently takes more than 1.5
> seconds to execute the query below. I did a dbcc pintable
> for ALL the tables in the query and that did not help
> either. It seemed to make it worse (3 seconds and above)
> Any idea what could be the issue here? The server
> is not really heavily taxed.
> The tables are small. They have very few rows.
> VGNCCB_ROLE 939
> VGNCCB_ROLE_JT 62389
> VGNCCB_GROUP_USER_JT 1364
>
> The problem Query:
> select
> ROLE_ID,
> NAME,
> DESCRIPTION,
> CREATE_DATE,
> MODIFIED_DATE
> FROM
> vign.VGNCCB_ROLE -- Clustered Indexed on Role ID
> WHERE
> ROLE_ID in
> (select ROLE_ID
> FROM
> vign.VGNCCB_ROLE_JT -- Non clustered indexes
> on USER_NAME AND non clustered on GROUP_ID
> WHERE
> USER_NAME = 'testRole' or GROUP_ID in (select
> GROUP_ID
> FROM
> vign.VGNCCB_GROUP_USER_JT -- Non clustered
> index on USER_NAME
> WHERE
> USER_NAME = 'testRole'))
> I'd appreciate it if someone could follow me in this
> thread to completion. Such a simple query should not take
> this long.
>
> TIA,
> Jack
> .
>

Performance problems with query

Guys,
I'm stumped. While its not pertinent to the
matter, we are running a Vignette content management
system on Win2k with Sql 2000 Enterprise on a cluster.
The server has 2 Gig of RAM , 2 CPU's and the database
size is 1.5G.
The query below is fired at login. The indexes
seem fine based on the query plan. When I look through
profiler, the query below takes a very high # of CPU
cycles and reads. It consistently takes more than 1.5
seconds to execute the query below. I did a dbcc pintable
for ALL the tables in the query and that did not help
either. It seemed to make it worse (3 seconds and above)
Any idea what could be the issue here? The server
is not really heavily taxed.
The tables are small. They have very few rows.
VGNCCB_ROLE939
VGNCCB_ROLE_JT62389
VGNCCB_GROUP_USER_JT1364
The problem Query:
select
ROLE_ID,
NAME,
DESCRIPTION,
CREATE_DATE,
MODIFIED_DATE
FROM
vign.VGNCCB_ROLE -- Clustered Indexed on Role ID
WHERE
ROLE_ID in
(select ROLE_ID
FROM
vign.VGNCCB_ROLE_JT -- Non clustered indexes
on USER_NAME AND non clustered on GROUP_ID
WHERE
USER_NAME = 'testRole' or GROUP_ID in (select
GROUP_ID
FROM
vign.VGNCCB_GROUP_USER_JT -- Non clustered
index on USER_NAME
WHERE
USER_NAME = 'testRole'))
I'd appreciate it if someone could follow me in this
thread to completion. Such a simple query should not take
this long.
TIA,
Jack
..
See my reply to your previous post from this morning.
"Jack A" <anonymous@.discussions.microsoft.com> wrote in message
news:fc6001c43e8b$7d505750$a301280a@.phx.gbl...
> Guys,
> I'm stumped. While its not pertinent to the
> matter, we are running a Vignette content management
> system on Win2k with Sql 2000 Enterprise on a cluster.
> The server has 2 Gig of RAM , 2 CPU's and the database
> size is 1.5G.
> The query below is fired at login. The indexes
> seem fine based on the query plan. When I look through
> profiler, the query below takes a very high # of CPU
> cycles and reads. It consistently takes more than 1.5
> seconds to execute the query below. I did a dbcc pintable
> for ALL the tables in the query and that did not help
> either. It seemed to make it worse (3 seconds and above)
> Any idea what could be the issue here? The server
> is not really heavily taxed.
> The tables are small. They have very few rows.
> VGNCCB_ROLE 939
> VGNCCB_ROLE_JT 62389
> VGNCCB_GROUP_USER_JT 1364
>
> The problem Query:
> select
> ROLE_ID,
> NAME,
> DESCRIPTION,
> CREATE_DATE,
> MODIFIED_DATE
> FROM
> vign.VGNCCB_ROLE -- Clustered Indexed on Role ID
> WHERE
> ROLE_ID in
> (select ROLE_ID
> FROM
> vign.VGNCCB_ROLE_JT -- Non clustered indexes
> on USER_NAME AND non clustered on GROUP_ID
> WHERE
> USER_NAME = 'testRole' or GROUP_ID in (select
> GROUP_ID
> FROM
> vign.VGNCCB_GROUP_USER_JT -- Non clustered
> index on USER_NAME
> WHERE
> USER_NAME = 'testRole'))
> I'd appreciate it if someone could follow me in this
> thread to completion. Such a simple query should not take
> this long.
>
> TIA,
> Jack
> .
>

Performance problems with query

Guys,
I'm stumped. While its not pertinent to the
matter, we are running a Vignette content management
system on Win2k with Sql 2000 Enterprise on a cluster.
The server has 2 Gig of RAM , 2 CPU's and the database
size is 1.5G.

The query below is fired at login. The indexes
seem fine based on the query plan. When I look through
profiler, the query below takes a very high # of CPU
cycles and reads. It consistently takes more than 1.5
seconds to execute the query below. I did a dbcc pintable
for ALL the tables in the query and that did not help
either. It seemed to make it worse (3 seconds and above)

Any idea what could be the issue here? The server
is not really heavily taxed.

The tables are small. They have very few rows.

VGNCCB_ROLE939
VGNCCB_ROLE_JT62389
VGNCCB_GROUP_USER_JT1364

The problem Query:

select
ROLE_ID,
NAME,
DESCRIPTION,
CREATE_DATE,
MODIFIED_DATE
FROM
vign.VGNCCB_ROLE -- Clustered Indexed on Role ID
WHERE
ROLE_ID in
(select ROLE_ID
FROM
vign.VGNCCB_ROLE_JT -- Non clustered indexes
on USER_NAME AND non clustered on GROUP_ID
WHERE
USER_NAME = 'testRole' or GROUP_ID in (select
GROUP_ID
FROM
vign.VGNCCB_GROUP_USER_JT -- Non clustered
index on USER_NAME
WHERE
USER_NAME = 'testRole'))

I'd appreciate it if someone could follow me in this
thread to completion. Such a simple query should not take
this long.

TIA,
Jack
...[posted and mailed, please reply in news]

Jack A (InformixMail@.yahoo.com) writes:
> The query below is fired at login. The indexes
> seem fine based on the query plan. When I look through
> profiler, the query below takes a very high # of CPU
> cycles and reads. It consistently takes more than 1.5
> seconds to execute the query below. I did a dbcc pintable
> for ALL the tables in the query and that did not help
> either. It seemed to make it worse (3 seconds and above)

DBCC PINTABLE is a command that very rarely is useful. If you have a
situation that you have a table that is referred to rearely, but
when it is referred to, you want the answers directly. Then you
have a case. Since these tables are referred to at log in and small,
I would assume that they are in memory anyway.

I could think of a possible rewrites of the query, but since this appears
to come from a third-party app, you don't seem to have any use for
that.

Without having the full information about the tables it is difficult
to say, but if it is correct that VGNCCB_ROLE_JT does not have a
clustered index, I think it is time to add one, and that would be
on (ROLE_ID). That could make the two indexes on USER_NAME and GROUP_ID
covering for the query, and could save you some bookmark lookups.

Another idea is to build an indexed view, and hope that SQL Server
will find the indexed view when looking for a query plan. But I am
not sure this is possible. And in any case, you need to have Enterprise
Edition for this to work.

I would encourage you to post the complete CREATE TABLE and CREATE INDEX
scripts for the tables. That makes it a little easier to guess.

--
Erland Sommarskog, SQL Server MVP, sommar@.algonet.se

Books Online for SQL Server SP3 at
http://www.microsoft.com/sql/techin.../2000/books.asp|||OK , Here goes with the table structure. BTW I've run DBCC reindex.

TABLE: VGNCCB_ROLE
PK__VGNCCB_ROLE__1FA39FB9clustered, unique, primary key located on
PRIMARY -- ROLE_ID

TABLE: VGNCCB_ROLE_JT
index_nameindex_descriptionindex_keys
PK__VGNCCB_ROLE_JT__218BE82Bclustered, unique, primary key located on
PRIMARY- ID
VGNCCB_ROLE_JT_INDEX1nonclustered located on PRIMARY- USER_NAME
VGNCCB_ROLE_JT_INDEX2nonclustered located on PRIMARY- GROUP_ID

TABLE: VGNCCB_GROUP_USER_JT
index_nameindex_descriptionindex_keys
PK__VGNCCB_GROUP_USE__1DBB5747clustered, unique, primary key located
on PRIMARY- ID
VGNCCB_GROUP_USER_JT_INDEX1nonclustered located on PRIMARY -GROUP_ID
VGNCCB_GROUP_USER_JT_INDEX2nonclustered located on PRIMARY-
USER_NAME|||Jack A (InformixMail@.yahoo.com) writes:
> OK , Here goes with the table structure. BTW I've run DBCC reindex.

Thanks, but I explicitly asked for CREATE TABLE and CREATE INDEX statements.
That could permit me see if it is possible to build an indexed view.

Also, in VGNCCB_ROLE_JT, I can't even see that there is a ROLE_ID
column.

You can script tables and indexes in Enterprise Manager or Query Analyzer.

--
Erland Sommarskog, SQL Server MVP, sommar@.algonet.se

Books Online for SQL Server SP3 at
http://www.microsoft.com/sql/techin.../2000/books.aspsql

Performance problems with query

Guys,
I'm stumped. While its not pertinent to the
matter, we are running a Vignette content management
system on Win2k with Sql 2000 Enterprise on a cluster.
The server has 2 Gig of RAM , 2 CPU's and the database
size is 1.5G.
The query below is fired at login. The indexes
seem fine based on the query plan. When I look through
profiler, the query below takes a very high # of CPU
cycles and reads. It consistently takes more than 1.5
seconds to execute the query below. I did a dbcc pintable
for ALL the tables in the query and that did not help
either. It seemed to make it worse (3 seconds and above)
Any idea what could be the issue here? The server
is not really heavily taxed.
The tables are small. They have very few rows.
VGNCCB_ROLE 939
VGNCCB_ROLE_JT 62389
VGNCCB_GROUP_USER_JT 1364
The problem Query:
select
ROLE_ID,
NAME,
DESCRIPTION,
CREATE_DATE,
MODIFIED_DATE
FROM
vign.VGNCCB_ROLE -- Clustered Indexed on Role ID
WHERE
ROLE_ID in
(select ROLE_ID
FROM
vign.VGNCCB_ROLE_JT -- Non clustered indexes
on USER_NAME AND non clustered on GROUP_ID
WHERE
USER_NAME = 'testRole' or GROUP_ID in (select
GROUP_ID
FROM
vign.VGNCCB_GROUP_USER_JT -- Non clustered
index on USER_NAME
WHERE
USER_NAME = 'testRole'))
I'd appreciate it if someone could follow me in this
thread to completion. Such a simple query should not take
this long.
TIA,
Jack
.See my reply to your previous post from this morning.
"Jack A" <anonymous@.discussions.microsoft.com> wrote in message
news:fc6001c43e8b$7d505750$a301280a@.phx.gbl...
> Guys,
> I'm stumped. While its not pertinent to the
> matter, we are running a Vignette content management
> system on Win2k with Sql 2000 Enterprise on a cluster.
> The server has 2 Gig of RAM , 2 CPU's and the database
> size is 1.5G.
> The query below is fired at login. The indexes
> seem fine based on the query plan. When I look through
> profiler, the query below takes a very high # of CPU
> cycles and reads. It consistently takes more than 1.5
> seconds to execute the query below. I did a dbcc pintable
> for ALL the tables in the query and that did not help
> either. It seemed to make it worse (3 seconds and above)
> Any idea what could be the issue here? The server
> is not really heavily taxed.
> The tables are small. They have very few rows.
> VGNCCB_ROLE 939
> VGNCCB_ROLE_JT 62389
> VGNCCB_GROUP_USER_JT 1364
>
> The problem Query:
> select
> ROLE_ID,
> NAME,
> DESCRIPTION,
> CREATE_DATE,
> MODIFIED_DATE
> FROM
> vign.VGNCCB_ROLE -- Clustered Indexed on Role ID
> WHERE
> ROLE_ID in
> (select ROLE_ID
> FROM
> vign.VGNCCB_ROLE_JT -- Non clustered indexes
> on USER_NAME AND non clustered on GROUP_ID
> WHERE
> USER_NAME = 'testRole' or GROUP_ID in (select
> GROUP_ID
> FROM
> vign.VGNCCB_GROUP_USER_JT -- Non clustered
> index on USER_NAME
> WHERE
> USER_NAME = 'testRole'))
> I'd appreciate it if someone could follow me in this
> thread to completion. Such a simple query should not take
> this long.
>
> TIA,
> Jack
> .
>

Monday, March 12, 2012

Performance optimization

Hi guys.
I'm trying to solve a performance problem I'm having with SQL Server.
I narrowed the cause of the deficiency to SQL Server's dynamic memory
allocation. ( I ran mmc.exe and used SQL Server: Memory Manager: Total
Server Memory )
This is the stored procedure that is causing the dynamic memory
allocation problem. There is a helper stored procedure that runs this
procedure while looping through a table.
My eyes have been trained to this code and I'm probably missing
something really simple. Can anyone lend me a fresh pair of eyes?
Thanks,
Ben
CREATE PROCEDURE CalculateCycleCount (@.currentEntity float(20),
@.startDate char(20), @.endDate char(20)) as
SET NOCOUNT ON
DECLARE @.level int
DECLARE @.ErrorCode int
Set @.ErrorCode = 0
DECLARE @.startDateDT datetime
DECLARE @.endDateDT datetime
Set @.startDateDT = convert(datetime, @.startDate)
Set @.endDateDT = convert(datetime, @.endDate)
CREATE TABLE #stack (entityID float(20), level int, plant char(255),
names char(100), Posted int, Accurate int )
/* this creates a temp table called #stack that recursively moves
through the plant table pushing and popping */
/* until it gets the entire tree calculated */
INSERT #stack
SELECT P.ID, 1, P.Plant, P.PlantName, C.Posted, C.Accurate
FROM tbl_Plant P Left Outer Join tbl_Cycle_Count_Temp C ON P.Plant
= C.Plnt
WHERE P.ID = @.currentEntity AND ((C.Date >= @.startDateDT AND C.Date
< @.endDateDT) OR C.Posted Is NULL)
SELECT @.level = 1
CREATE TABLE #tbl_temp_sum (Sls_Office char(255), Posted int, Accurate
int)
WHILE @.level > 0
BEGIN
IF EXISTS (SELECT * FROM #stack WHERE level = @.level)
BEGIN
SELECT @.currentEntity = entityID
FROM #stack
WHERE level = @.level
INSERT #tbl_temp_sum
SELECT S.plant, S.Posted, S.Accurate
FROM #stack S
WHERE S.entityID = @.currentEntity
DELETE FROM #stack
WHERE level = @.level
AND entityID = @.currentEntity
INSERT #stack
SELECT P.ID, @.level + 1, P.Plant, P.PlantName, C.Posted,
C.Accurate
FROM tbl_Plant P Left Outer Join tbl_Cycle_Count_Temp C ON
P.Plant = C.Plnt
WHERE P.parent = @.currentEntity AND ((C.Date >=
@.startDateDT AND C.Date < @.endDateDT) OR C.Posted Is NULL)
IF @.@.ROWCOUNT > 0
SELECT @.level = @.level + 1
END
ELSE
SELECT @.level = @.level - 1
END -- WHILE
DECLARE @.count int;
DECLARE @.plantName nvarchar(50);
SELECT @.plantName = P.Plant FROM tbl_Plant P WHERE P.ID =
@.currentEntity;
SELECT @.count = COUNT(*) FROM #tbl_temp_sum;
if ( @.count > 0 )
BEGIN
INSERT INTO tbl_Cycle_Count SELECT @.plantName, SUM(Posted),
SUM(Accurate), @.endDate FROM #tbl_temp_sum;
END
--SELECT COUNT(*) AS Cnt, SUM(Posted) AS Posted, SUM(Accurate) as
Accurate FROM #tbl_temp_sum
SET @.ErrorCode = @.@.Error
Return @.ErrorCode
GOHi
Without knowing the table structure and data it is harder to diagnose your
issue. There is a lack of error handling see
http://www.sommarskog.se/error-handling-II.html and your temporary tables
should probably be created at the start (if they are really needed!)
Try using the debug option in Query Analyser (open the object browser(F8),
select the procedure, right click and choose debug), to step through the cod
e
and see the values.
John
"benis.ong@.gmail.com" wrote:

> Hi guys.
> I'm trying to solve a performance problem I'm having with SQL Server.
> I narrowed the cause of the deficiency to SQL Server's dynamic memory
> allocation. ( I ran mmc.exe and used SQL Server: Memory Manager: Total
> Server Memory )
> This is the stored procedure that is causing the dynamic memory
> allocation problem. There is a helper stored procedure that runs this
> procedure while looping through a table.
> My eyes have been trained to this code and I'm probably missing
> something really simple. Can anyone lend me a fresh pair of eyes?
>
> Thanks,
> Ben
> CREATE PROCEDURE CalculateCycleCount (@.currentEntity float(20),
> @.startDate char(20), @.endDate char(20)) as
> SET NOCOUNT ON
> DECLARE @.level int
> DECLARE @.ErrorCode int
> Set @.ErrorCode = 0
> DECLARE @.startDateDT datetime
> DECLARE @.endDateDT datetime
> Set @.startDateDT = convert(datetime, @.startDate)
> Set @.endDateDT = convert(datetime, @.endDate)
> CREATE TABLE #stack (entityID float(20), level int, plant char(255),
> names char(100), Posted int, Accurate int )
> /* this creates a temp table called #stack that recursively moves
> through the plant table pushing and popping */
> /* until it gets the entire tree calculated */
> INSERT #stack
> SELECT P.ID, 1, P.Plant, P.PlantName, C.Posted, C.Accurate
> FROM tbl_Plant P Left Outer Join tbl_Cycle_Count_Temp C ON P.Plant
> = C.Plnt
> WHERE P.ID = @.currentEntity AND ((C.Date >= @.startDateDT AND C.Date
> < @.endDateDT) OR C.Posted Is NULL)
> SELECT @.level = 1
> CREATE TABLE #tbl_temp_sum (Sls_Office char(255), Posted int, Accurate
> int)
> WHILE @.level > 0
> BEGIN
> IF EXISTS (SELECT * FROM #stack WHERE level = @.level)
> BEGIN
> SELECT @.currentEntity = entityID
> FROM #stack
> WHERE level = @.level
> INSERT #tbl_temp_sum
> SELECT S.plant, S.Posted, S.Accurate
> FROM #stack S
> WHERE S.entityID = @.currentEntity
> DELETE FROM #stack
> WHERE level = @.level
> AND entityID = @.currentEntity
> INSERT #stack
> SELECT P.ID, @.level + 1, P.Plant, P.PlantName, C.Posted,
> C.Accurate
> FROM tbl_Plant P Left Outer Join tbl_Cycle_Count_Temp C ON
> P.Plant = C.Plnt
> WHERE P.parent = @.currentEntity AND ((C.Date >=
> @.startDateDT AND C.Date < @.endDateDT) OR C.Posted Is NULL)
> IF @.@.ROWCOUNT > 0
> SELECT @.level = @.level + 1
> END
> ELSE
> SELECT @.level = @.level - 1
> END -- WHILE
> DECLARE @.count int;
> DECLARE @.plantName nvarchar(50);
> SELECT @.plantName = P.Plant FROM tbl_Plant P WHERE P.ID =
> @.currentEntity;
> SELECT @.count = COUNT(*) FROM #tbl_temp_sum;
> if ( @.count > 0 )
> BEGIN
> INSERT INTO tbl_Cycle_Count SELECT @.plantName, SUM(Posted),
> SUM(Accurate), @.endDate FROM #tbl_temp_sum;
> END
> --SELECT COUNT(*) AS Cnt, SUM(Posted) AS Posted, SUM(Accurate) as
> Accurate FROM #tbl_temp_sum
> SET @.ErrorCode = @.@.Error
> Return @.ErrorCode
> GO
>

Performance optimization

Hi guys.
I'm trying to solve a performance problem I'm having with SQL Server.
I narrowed the cause of the deficiency to SQL Server's dynamic memory
allocation. ( I ran mmc.exe and used SQL Server: Memory Manager: Total
Server Memory )
This is the stored procedure that is causing the dynamic memory
allocation problem. There is a helper stored procedure that runs this
procedure while looping through a table.
My eyes have been trained to this code and I'm probably missing
something really simple. Can anyone lend me a fresh pair of eyes?
Thanks,
Ben
CREATE PROCEDURE CalculateCycleCount (@.currentEntity float(20),
@.startDate char(20), @.endDate char(20)) as
SET NOCOUNT ON
DECLARE @.level int
DECLARE @.ErrorCode int
Set @.ErrorCode = 0
DECLARE @.startDateDT datetime
DECLARE @.endDateDT datetime
Set @.startDateDT = convert(datetime, @.startDate)
Set @.endDateDT = convert(datetime, @.endDate)
CREATE TABLE #stack (entityID float(20), level int, plant char(255),
names char(100), Posted int, Accurate int )
/* this creates a temp table called #stack that recursively moves
through the plant table pushing and popping */
/* until it gets the entire tree calculated */
INSERT #stack
SELECT P.ID, 1, P.Plant, P.PlantName, C.Posted, C.Accurate
FROM tbl_Plant P Left Outer Join tbl_Cycle_Count_Temp C ON P.Plant
= C.Plnt
WHERE P.ID = @.currentEntity AND ((C.Date >= @.startDateDT AND C.Date
< @.endDateDT) OR C.Posted Is NULL)
SELECT @.level = 1
CREATE TABLE #tbl_temp_sum (Sls_Office char(255), Posted int, Accurate
int)
WHILE @.level > 0
BEGIN
IF EXISTS (SELECT * FROM #stack WHERE level = @.level)
BEGIN
SELECT @.currentEntity = entityID
FROM #stack
WHERE level = @.level
INSERT #tbl_temp_sum
SELECT S.plant, S.Posted, S.Accurate
FROM #stack S
WHERE S.entityID = @.currentEntity
DELETE FROM #stack
WHERE level = @.level
AND entityID = @.currentEntity
INSERT #stack
SELECT P.ID, @.level + 1, P.Plant, P.PlantName, C.Posted,
C.Accurate
FROM tbl_Plant P Left Outer Join tbl_Cycle_Count_Temp C ON
P.Plant = C.Plnt
WHERE P.parent = @.currentEntity AND ((C.Date >=
@.startDateDT AND C.Date < @.endDateDT) OR C.Posted Is NULL)
IF @.@.ROWCOUNT > 0
SELECT @.level = @.level + 1
END
ELSE
SELECT @.level = @.level - 1
END -- WHILE
DECLARE @.count int;
DECLARE @.plantName nvarchar(50);
SELECT @.plantName = P.Plant FROM tbl_Plant P WHERE P.ID =
@.currentEntity;
SELECT @.count = COUNT(*) FROM #tbl_temp_sum;
if ( @.count > 0 )
BEGIN
INSERT INTO tbl_Cycle_Count SELECT @.plantName, SUM(Posted),
SUM(Accurate), @.endDate FROM #tbl_temp_sum;
END
--SELECT COUNT(*) AS Cnt, SUM(Posted) AS Posted, SUM(Accurate) as
Accurate FROM #tbl_temp_sum
SET @.ErrorCode = @.@.Error
Return @.ErrorCode
GO
Hi
Without knowing the table structure and data it is harder to diagnose your
issue. There is a lack of error handling see
http://www.sommarskog.se/error-handling-II.html and your temporary tables
should probably be created at the start (if they are really needed!)
Try using the debug option in Query Analyser (open the object browser(F8),
select the procedure, right click and choose debug), to step through the code
and see the values.
John
"benis.ong@.gmail.com" wrote:

> Hi guys.
> I'm trying to solve a performance problem I'm having with SQL Server.
> I narrowed the cause of the deficiency to SQL Server's dynamic memory
> allocation. ( I ran mmc.exe and used SQL Server: Memory Manager: Total
> Server Memory )
> This is the stored procedure that is causing the dynamic memory
> allocation problem. There is a helper stored procedure that runs this
> procedure while looping through a table.
> My eyes have been trained to this code and I'm probably missing
> something really simple. Can anyone lend me a fresh pair of eyes?
>
> Thanks,
> Ben
> CREATE PROCEDURE CalculateCycleCount (@.currentEntity float(20),
> @.startDate char(20), @.endDate char(20)) as
> SET NOCOUNT ON
> DECLARE @.level int
> DECLARE @.ErrorCode int
> Set @.ErrorCode = 0
> DECLARE @.startDateDT datetime
> DECLARE @.endDateDT datetime
> Set @.startDateDT = convert(datetime, @.startDate)
> Set @.endDateDT = convert(datetime, @.endDate)
> CREATE TABLE #stack (entityID float(20), level int, plant char(255),
> names char(100), Posted int, Accurate int )
> /* this creates a temp table called #stack that recursively moves
> through the plant table pushing and popping */
> /* until it gets the entire tree calculated */
> INSERT #stack
> SELECT P.ID, 1, P.Plant, P.PlantName, C.Posted, C.Accurate
> FROM tbl_Plant P Left Outer Join tbl_Cycle_Count_Temp C ON P.Plant
> = C.Plnt
> WHERE P.ID = @.currentEntity AND ((C.Date >= @.startDateDT AND C.Date
> < @.endDateDT) OR C.Posted Is NULL)
> SELECT @.level = 1
> CREATE TABLE #tbl_temp_sum (Sls_Office char(255), Posted int, Accurate
> int)
> WHILE @.level > 0
> BEGIN
> IF EXISTS (SELECT * FROM #stack WHERE level = @.level)
> BEGIN
> SELECT @.currentEntity = entityID
> FROM #stack
> WHERE level = @.level
> INSERT #tbl_temp_sum
> SELECT S.plant, S.Posted, S.Accurate
> FROM #stack S
> WHERE S.entityID = @.currentEntity
> DELETE FROM #stack
> WHERE level = @.level
> AND entityID = @.currentEntity
> INSERT #stack
> SELECT P.ID, @.level + 1, P.Plant, P.PlantName, C.Posted,
> C.Accurate
> FROM tbl_Plant P Left Outer Join tbl_Cycle_Count_Temp C ON
> P.Plant = C.Plnt
> WHERE P.parent = @.currentEntity AND ((C.Date >=
> @.startDateDT AND C.Date < @.endDateDT) OR C.Posted Is NULL)
> IF @.@.ROWCOUNT > 0
> SELECT @.level = @.level + 1
> END
> ELSE
> SELECT @.level = @.level - 1
> END -- WHILE
> DECLARE @.count int;
> DECLARE @.plantName nvarchar(50);
> SELECT @.plantName = P.Plant FROM tbl_Plant P WHERE P.ID =
> @.currentEntity;
> SELECT @.count = COUNT(*) FROM #tbl_temp_sum;
> if ( @.count > 0 )
> BEGIN
> INSERT INTO tbl_Cycle_Count SELECT @.plantName, SUM(Posted),
> SUM(Accurate), @.endDate FROM #tbl_temp_sum;
> END
> --SELECT COUNT(*) AS Cnt, SUM(Posted) AS Posted, SUM(Accurate) as
> Accurate FROM #tbl_temp_sum
> SET @.ErrorCode = @.@.Error
> Return @.ErrorCode
> GO
>

Performance optimization

Hi guys.
I'm trying to solve a performance problem I'm having with SQL Server.
I narrowed the cause of the deficiency to SQL Server's dynamic memory
allocation. ( I ran mmc.exe and used SQL Server: Memory Manager: Total
Server Memory )
This is the stored procedure that is causing the dynamic memory
allocation problem. There is a helper stored procedure that runs this
procedure while looping through a table.
My eyes have been trained to this code and I'm probably missing
something really simple. Can anyone lend me a fresh pair of eyes?
Thanks,
Ben
CREATE PROCEDURE CalculateCycleCount (@.currentEntity float(20),
@.startDate char(20), @.endDate char(20)) as
SET NOCOUNT ON
DECLARE @.level int
DECLARE @.ErrorCode int
Set @.ErrorCode = 0
DECLARE @.startDateDT datetime
DECLARE @.endDateDT datetime
Set @.startDateDT = convert(datetime, @.startDate)
Set @.endDateDT = convert(datetime, @.endDate)
CREATE TABLE #stack (entityID float(20), level int, plant char(255),
names char(100), Posted int, Accurate int )
/* this creates a temp table called #stack that recursively moves
through the plant table pushing and popping */
/* until it gets the entire tree calculated */
INSERT #stack
SELECT P.ID, 1, P.Plant, P.PlantName, C.Posted, C.Accurate
FROM tbl_Plant P Left Outer Join tbl_Cycle_Count_Temp C ON P.Plant
= C.Plnt
WHERE P.ID = @.currentEntity AND ((C.Date >= @.startDateDT AND C.Date
< @.endDateDT) OR C.Posted Is NULL)
SELECT @.level = 1
CREATE TABLE #tbl_temp_sum (Sls_Office char(255), Posted int, Accurate
int)
WHILE @.level > 0
BEGIN
IF EXISTS (SELECT * FROM #stack WHERE level = @.level)
BEGIN
SELECT @.currentEntity = entityID
FROM #stack
WHERE level = @.level
INSERT #tbl_temp_sum
SELECT S.plant, S.Posted, S.Accurate
FROM #stack S
WHERE S.entityID = @.currentEntity
DELETE FROM #stack
WHERE level = @.level
AND entityID = @.currentEntity
INSERT #stack
SELECT P.ID, @.level + 1, P.Plant, P.PlantName, C.Posted,
C.Accurate
FROM tbl_Plant P Left Outer Join tbl_Cycle_Count_Temp C ON
P.Plant = C.Plnt
WHERE P.parent = @.currentEntity AND ((C.Date >= @.startDateDT AND C.Date < @.endDateDT) OR C.Posted Is NULL)
IF @.@.ROWCOUNT > 0
SELECT @.level = @.level + 1
END
ELSE
SELECT @.level = @.level - 1
END -- WHILE
DECLARE @.count int;
DECLARE @.plantName nvarchar(50);
SELECT @.plantName = P.Plant FROM tbl_Plant P WHERE P.ID = @.currentEntity;
SELECT @.count = COUNT(*) FROM #tbl_temp_sum;
if ( @.count > 0 )
BEGIN
INSERT INTO tbl_Cycle_Count SELECT @.plantName, SUM(Posted),
SUM(Accurate), @.endDate FROM #tbl_temp_sum;
END
--SELECT COUNT(*) AS Cnt, SUM(Posted) AS Posted, SUM(Accurate) as
Accurate FROM #tbl_temp_sum
SET @.ErrorCode = @.@.Error
Return @.ErrorCode
GOHi
Without knowing the table structure and data it is harder to diagnose your
issue. There is a lack of error handling see
http://www.sommarskog.se/error-handling-II.html and your temporary tables
should probably be created at the start (if they are really needed!)
Try using the debug option in Query Analyser (open the object browser(F8),
select the procedure, right click and choose debug), to step through the code
and see the values.
John
"benis.ong@.gmail.com" wrote:
> Hi guys.
> I'm trying to solve a performance problem I'm having with SQL Server.
> I narrowed the cause of the deficiency to SQL Server's dynamic memory
> allocation. ( I ran mmc.exe and used SQL Server: Memory Manager: Total
> Server Memory )
> This is the stored procedure that is causing the dynamic memory
> allocation problem. There is a helper stored procedure that runs this
> procedure while looping through a table.
> My eyes have been trained to this code and I'm probably missing
> something really simple. Can anyone lend me a fresh pair of eyes?
>
> Thanks,
> Ben
> CREATE PROCEDURE CalculateCycleCount (@.currentEntity float(20),
> @.startDate char(20), @.endDate char(20)) as
> SET NOCOUNT ON
> DECLARE @.level int
> DECLARE @.ErrorCode int
> Set @.ErrorCode = 0
> DECLARE @.startDateDT datetime
> DECLARE @.endDateDT datetime
> Set @.startDateDT = convert(datetime, @.startDate)
> Set @.endDateDT = convert(datetime, @.endDate)
> CREATE TABLE #stack (entityID float(20), level int, plant char(255),
> names char(100), Posted int, Accurate int )
> /* this creates a temp table called #stack that recursively moves
> through the plant table pushing and popping */
> /* until it gets the entire tree calculated */
> INSERT #stack
> SELECT P.ID, 1, P.Plant, P.PlantName, C.Posted, C.Accurate
> FROM tbl_Plant P Left Outer Join tbl_Cycle_Count_Temp C ON P.Plant
> = C.Plnt
> WHERE P.ID = @.currentEntity AND ((C.Date >= @.startDateDT AND C.Date
> < @.endDateDT) OR C.Posted Is NULL)
> SELECT @.level = 1
> CREATE TABLE #tbl_temp_sum (Sls_Office char(255), Posted int, Accurate
> int)
> WHILE @.level > 0
> BEGIN
> IF EXISTS (SELECT * FROM #stack WHERE level = @.level)
> BEGIN
> SELECT @.currentEntity = entityID
> FROM #stack
> WHERE level = @.level
> INSERT #tbl_temp_sum
> SELECT S.plant, S.Posted, S.Accurate
> FROM #stack S
> WHERE S.entityID = @.currentEntity
> DELETE FROM #stack
> WHERE level = @.level
> AND entityID = @.currentEntity
> INSERT #stack
> SELECT P.ID, @.level + 1, P.Plant, P.PlantName, C.Posted,
> C.Accurate
> FROM tbl_Plant P Left Outer Join tbl_Cycle_Count_Temp C ON
> P.Plant = C.Plnt
> WHERE P.parent = @.currentEntity AND ((C.Date >=> @.startDateDT AND C.Date < @.endDateDT) OR C.Posted Is NULL)
> IF @.@.ROWCOUNT > 0
> SELECT @.level = @.level + 1
> END
> ELSE
> SELECT @.level = @.level - 1
> END -- WHILE
> DECLARE @.count int;
> DECLARE @.plantName nvarchar(50);
> SELECT @.plantName = P.Plant FROM tbl_Plant P WHERE P.ID => @.currentEntity;
> SELECT @.count = COUNT(*) FROM #tbl_temp_sum;
> if ( @.count > 0 )
> BEGIN
> INSERT INTO tbl_Cycle_Count SELECT @.plantName, SUM(Posted),
> SUM(Accurate), @.endDate FROM #tbl_temp_sum;
> END
> --SELECT COUNT(*) AS Cnt, SUM(Posted) AS Posted, SUM(Accurate) as
> Accurate FROM #tbl_temp_sum
> SET @.ErrorCode = @.@.Error
> Return @.ErrorCode
> GO
>