Я последовательно смог воспроизвести серьезную проблему производительности параметризации с Coldfusion 10 с запросом SQL Server 2008 R2 и было бы интересно узнать, что получают другие. Код ниже.Воспроизводимая проблема производительности CFQUERYPARAM в Coldfusion 10
Что делает тест? Он создает таблицу со 100 строками. Столбец данных пуст во всех, кроме одного. Затем он запускает запрос Coldfusion 10 раз, наполовину используя cfqueryparam и половину, используя простую строку. Он возвращает список с временем отклика для каждого. Когда я запускаю это, помимо начальных вызовов, параметризованный запрос выполняется намного медленнее (примерно в 10-100 раз).
Что происходит в SQL Server? Я не вижу различий в SQL-сервере. В обоих случаях кеш плана указывает практически идентичные планы (один, очевидно, параметризуется), и профайлер показывает быстрые ответы для обоих. Однако Coldfusion борется с параметризованным запросом.
В чем проблема? Любопытно, что если я изменю varchar на nvarchar, проблема исчезнет. Или, если я перемещаю непустую в начало, то оба ответа медленны (go figure). Если я сделаю все записи пустыми или не пустыми, то опять проблема не будет. Это должно быть смесь. Я не могу воспроизвести проблему в CF9, но не пробовал CF11.
<cfset datasource="yourdatasource" />
<cfquery name="createdata" datasource="#datasource#">
--EMPTY PREVIOUS TESTS
IF OBJECT_ID('aaatest', 'U') IS NOT NULL
BEGIN
TRUNCATE TABLE aaatest;
DROP TABLE aaatest;
END
--CREATE TABLE TO CONTAIN DATA
CREATE TABLE [dbo].[aaatest](
[id] [int] NOT NULL,
[somedata] [varchar](max) NULL,
[somekey] [int] NOT NULL
) ON [PRIMARY];
--INSERT 100 ROWS WITH 99 BLANK AND 1 NON-BLANK
WITH datatable AS (
SELECT 1 id
UNION all
SELECT id + 1
FROM datatable
WHERE id + 1 <= 100
)
INSERT INTO aaatest(id,somekey,somedata)
SELECT id,1,case when id=99 then 'A' else '' end
FROM datatable;
</cfquery>
<cfset results=[] />
<cfloop from="1" to="10" index="n">
<!--- use parameters for every other test --->
<cfset useParameters = (n mod 2 is 0) />
<cfquery name="myquery" datasource="#datasource#" result="result">
SELECT somedata
FROM aaatest
WHERE somekey=
<cfif useParameters>
<cfqueryparam value="1" CFSQLType="CF_SQL_INTEGER" />
<cfelse>
1
</cfif>
</cfquery>
<!--- store results with parameter test marked with a P --->
<cfset arrayAppend(results,(useParameters?'P':'')&result.executiontime) />
</cfloop>
<cfdump var="#results#" />
Просмотрите план выполнения каждой версии теста и посмотрите, не проливает ли свет на сцену? –
сделал. Я очистил кэш плана и выполнил эти два запроса. Там было двое. Они были идентичны, кроме того, что они были параметризованы. Я также упомянул, что профайлер показывает, что SQL работает одинаково. Это либо ColdFusion, либо интерфейс базы данных. Тем не менее, я должен добавить, что, когда тест запускается из .NET, все в порядке (это, вероятно, использует тот же ODBC - хотя, очевидно, не Java). – Raspin
Обычно я использую 'cf_sql_numeric'. Кажется, что ваш тест быстрее. Btw. как вы читаете план кеши с SQL Server? –