У меня есть следующий запрос, который выполняется в 16 мс - 30 мс.Медленный запрос с поиском cfqueryparam на индексированном столбце, содержащем хеши
<cfquery name="local.test1" datasource="imagecdn">
SELECT hash FROM jobs WHERE hash in(
'EBDA95630915EB80709C69089315399B',
'3617B8E6CF0C62ECBD3C48DDF8585466',
'D519A38F09FDA868A2FEF1C55C9FEE76',
'135F94C3774F7719CFF8FF3A275D2D05',
'D58FAE69C559273D8427673A08193789',
'2BD7276F209768F2FCA6635659D7922A',
'B1E3CFBFCCFF6F5B48A849A050E6D424',
'2288F5B8A797F5302E8CA24323617236',
'8951883E36B5D38A4643DFAA0396BF13',
'839210BD564E30BE1355D1A6D4EF7081',
'ED4A2CB0C28B608C29576819CF7BE19B',
'CB26925A4874945B810707D5FF0B91F2',
'33B2FC229F0CC797A02AD163CDBA0875',
'624986E7547DBAC0F47B3005CFDE0A16',
'6F692C289BD805CEE41EF59F83F16F4D',
'8551F0033C617BD9EADAAD6CEC4B3E9E',
'94C3C0A74C2DE085FF9F1BBF928821A4',
'28DC1A9D2A69C2EDF5E6C0E6368A0B3C'
)
</cfquery>
Если я выполняю тот же запрос, но использую cfqueryparam, он работает в 500 мс - 2000 мс.
<cfset local.hashes = "[list of the same ids as above]">
<cfquery name="local.test2" datasource="imagecdn">
SELECT hash FROM jobs WHERE hash in(
<cfqueryparam cfsqltype="cf_sql_varchar" value="#local.hashes#" list="yes">
)
</cfquery>
В таблице имеется примерно 60 000 строк. Столбец «хэш» - это varchar (50) и имеет уникальный некластеризованный индекс, но не является первичным ключом. Сервер БД - MSSQL 2008. На веб-сервере установлена последняя версия CF9.
Любая идея, почему cfqueryparam заставляет производительность бомбить? Он ведет себя так каждый раз, независимо от того, сколько раз я обновляю страницу. Если я скрою список всего лишь на 2 или 3 хэша, он все равно будет работать примерно на 150-200 мс. Когда я удаляю cfqueryparam, производительность будет такой, как ожидалось. В этой ситуации есть возможность для SQL-инъекций, и, следовательно, использование cfqueryparam, безусловно, будет предпочтительным, но не должно принимать 100 мс, чтобы найти 2 записи из индексированного столбца.
редактирует:
Мы используем хэши, сгенерированные
hash()
не UUIDs или Guids. Хэш генерируетсяhash(SerializeJSON({ struct }))
, который содержит план выполнения ряда операций, выполняемых на изображении. Цель этого заключается в том, что он позволяет нам знать перед вставкой и перед запросом точный уникальный идентификатор для этой структуры. Эти хэши действуют как «индекс» того, какие структуры уже хранятся в БД. В дополнение к хэшам такая же структура будет хешем с тем же результатом, что неверно для UUIDS и GUIDS.Запрос выполняется на 5 разных серверах CF9, и все они имеют одинаковое поведение. Для меня это исключает мысль о том, что CF9 кэширует что-то. Все серверы подключаются к одному и тому же БД, поэтому, если кэширование происходит, это должен быть уровень БД.
Вы пытались использовать только cf_sql_char вместо varchar? Это может заставить MSSQL более внимательно рассмотреть массив и дать вам лучший план выполнения. Очевидно, что план, который он выдает из кеша, не так эффективен, как тот, который он компилирует в режиме реального времени. Также попробуйте добавить подсказку индекса. Запустите анализатор трассировки на нем, если вы можете изолировать его в dev - может дать вам некоторые подсказки в плане выполнения. это все, что у меня есть :) –
Возможно, это потому, что он не может повторно использовать инструкцию подготовки для списков, поэтому он перекомпилит каждый раз ... Если вы уверены, что используете свою собственную логику для предотвращения внедрения sql, возможно, это целесообразно пропустить cfqueryparam для этого. – Henry
Вот несколько способов улучшить производительность SELECT IN. Http://florianreischl.blogspot.ca/2012/03/performance-comparison-of-sql-server.html – Henry