Skip to main content
Participant
September 17, 2008
Question

CFStoredProc Behavior Issues

  • September 17, 2008
  • 1 reply
  • 587 views
This has to be one of the craziest things I have seen with CF in a long time. We have a stored proc that is not playing nicely. When the stored proc, written in SQL 2005 is ran in Management Studio, it runs in less than a second. When we try and run this same proc in CF8 using cfstoredproc, it runs around 20+ secs. We tried 3 different approaches to diagnose this problem but to no avail.

1)
<cfstoredproc procedure="usp_University_Geography_Sales" datasource="#request.dsn#">
<cfprocparam type="IN" cfsqltype="CF_SQL_INTEGER" value="#companyid#">
<cfprocparam type="IN" cfsqltype="CF_SQL_VARCHAR" value="#dateFromLastYear#">
<cfprocparam type="IN" cfsqltype="CF_SQL_VARCHAR" value="#dateToLastYear#">
<cfprocparam type="IN" cfsqltype="CF_SQL_INTEGER" value="#timeyearid#">
<cfprocparam type="IN" cfsqltype="CF_SQL_VARCHAR" value="#reportType#">
<cfprocresult name="qryRTDLY">
</cfstoredproc>

2)
<cfquery name="qryRTDLY" datasource="#request.dsn#">
Exec spdr..usp_University_Geography_Sales #companyid#,'#dateFromLastYear#','#dateToLastYear#',#timeyearid#,'#reportType#'
</cfquery>

3)
DECLARE
@companyID int,
@startDate smalldatetime,
@endDate smalldatetime,
@timeYearID int,
@grouptype varchar(10)

SET @companyID = #companyid#
SET @startDate = '#dateFrom#'
SET @endDate = '#dateTo#'
SET @timeYearID = #timeyearid#
SET @grouptype = '#reportType#'


--Hardcode TimeYearDivisionID to '5' which is for all year
DECLARE @timeYearDivisionID INT
SET @timeYearDivisionID = 5

--Set GeographyType
DECLARE @geographyTypeID INT
IF @CompanyID = 2
SET @geographyTypeID = 8
IF @CompanyID = 32
SET @geographyTypeID = 9
IF @CompanyID NOT IN (2,32)
SET @geographyTypeID = 0

SELECT
@companyID companyID,
@timeYearID timeYearID,
@timeYearDivisionID timeYearDivisionID,
@startDate startDate,
@endDate endDate,
gzt.GeographyID,
g.GeographyDescription,
ISNULL(SUM(sales.sales),0) as Sales
FROM
Geography_Zip_Time gzt
INNER JOIN Geography g
ON gzt.GeographyID = g.GeographyID
AND gzt.TimeYearID = g.TimeYearID
AND gzt.TimeYearDivisionID = g.TimeYearDivisionID
LEFT JOIN
(
SELECT
inv.InvoiceShipToZipID as ShipToZipID,
SUM(inv.invoicelinetotal) sales
FROM
SPDRWarehouse.dbo.InvoiceHistory inv
INNER JOIN dbo.udf_Active_Universities_by_CompanyID(@companyID, @grouptype) Unv
ON inv.InvoiceToAccountid = Unv.accountid
INNER JOIN Item
ON inv.itemid = Item.itemid
AND Item.ItemClassCode between 'AA' and 'ZZ'
WHERE
inv.InvoiceDate BETWEEN @startDate AND @endDate
GROUP BY
inv.InvoiceShipToZipID
) sales
ON gzt.ZipID = sales.ShipToZipID
WHERE
gzt.TimeYearID = @TimeYearID
AND gzt.TimeYearDivisionID = 5
AND gzt.geographytypeid = @geographyTypeID
GROUP BY
gzt.GeographyID,
g.GeographyDescription

1 and 2 take 20+ secs, 3 is less than a second. All 3 are the same query just called differently. Any ideas why?? Thanks in advance.

Kevin W. Ryan
Senior Database Applications Engineer
This topic has been closed for replies.

1 reply

Inspiring
September 17, 2008
Have you reviewed the sql execution plans for the stored procedure vs the in-line sql? I would also use the sql profiler to review what is happening in the database when you call each of statements. Checking for things like recompilations, etcetera.

Rhino72Author
Participant
September 17, 2008
Come to find out, when the stored proc was being called from CF, it was using a different query plan then the one being called in Management Studio. No matter what we did, we could not get the CF to use the better plan. We decided to add WITH RECONPILE to the stored procs in question, we were able to get the peformance we were looking for. We are still left with some questions in regards to this issue. Does the JVM cache a query plan or can it even affect a query plan?? Thanks for the help cfSearching
Inspiring
September 18, 2008
I do not think so. But I do not have an extremely deep understanding of the internal communications between jvm and database.

From what I know, CF uses PreparedStatements to call stored procedures. Initially the shell sql is sent to the database, which compiles it, generates a execution plan and adds the plan to its cache. Once the plan is stored in the database cache all subsequent calls of that procedure should theoretically use that same plan. So unless you cleared the cache and/or ran sp_recompile on the procedure, I am not surprised that SQL continued to use the same "bad" plan.

Why a different plan was generated, is very hard to say. There are many factors that might cause SQL to generate a different plan. Of course I am making the assumption that the query plan alone was entirely responsible for the time difference. Which may or may not be the case.