16ms-30ms에서 실행되는 다음 쿼리가 있습니다.해시가 포함 된 인덱싱 된 열에서 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을 사용하면 500ms ~ 2000ms에서 실행됩니다.
<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)이며 클러스터되지 않은 고유 한 인덱스가 있지만 기본 키는 아닙니다. DB 서버는 MSSQL 2008입니다. 웹 서버는 최신 버전의 CF9를 실행하고 있습니다.
cfqueryparam으로 인해 성능이 폭격하는 이유는 무엇입니까? 페이지를 새로 고침 한 횟수에 상관없이 매번이 방식으로 작동합니다. 목록을 2 ~ 3 개의 해시만으로 페어링하면 150 ~ 200 밀리 초일 때 성능이 떨어집니다. cfqueryparam을 제거하면 성능이 예상대로 유지됩니다. 이 상황에서는 SQL 주입 가능성이 있으므로 cfqueryparam을 사용하는 것이 좋습니다. 그러나 인덱스 된 열에서 2 개의 레코드를 찾으려면 100ms가 걸리지 않아야합니다.
편집 : 우리는 hash()
UUID가 아닌 나 GUIDS에 의해 생성 된 해시를 사용하는
. 해시는 이미지에서 실행할 작업 집합에 대한 계획이 포함 된
hash(SerializeJSON({ struct }))
에 의해 생성됩니다. 이것의 목적은 우리가 삽입 전에 그리고 그 구조에 대한 정확한 유일한 ID를 찾기 전에 알 수있게 해준다. 이 해시는 이미 DB에 저장된 구조의 "색인"역할을합니다. 또한 해시와 동일한 구조가 동일한 결과에 해시됩니다 (UUIDS 및 GUID에는 해당되지 않음).쿼리가 5 개의 다른 CF9 서버에서 실행되고 있으며 모두 동일한 동작을 나타냅니다. 나에게 이것은 CF9가 뭔가를 캐싱한다는 생각을 배제한다. 모든 서버가 똑같은 DB에 연결되므로 캐싱이 발생하면 DB 수준이어야합니다.
varchar 대신 cf_sql_char를 사용해 보셨습니까? MSSQL이 배열을 면밀히 살펴보고 더 나은 실행 계획을 제공하도록 강요 할 수 있습니다. 분명히 캐시에서 나오는 계획은 실시간으로 컴파일하는 계획만큼 효율적이지 않습니다. 또한 인덱스 힌트를 추가하십시오. 개발 분석기로 추적 분석기를 실행하면 실행 계획에 몇 가지 단서를 줄 수 있습니다. 그게 전부예요 :) –
목록에 대한 prepare 문을 다시 사용할 수 없기 때문에 매번 다시 컴파일됩니다. 왜냐하면 SQL 삽입을 방지하기 위해 자신의 논리를 사용하는 것이 확실하면 cfqueryparam을 건너 뛰는 것이 적합 할 수 있습니다. 이것 때문에. – Henry
다음은 SELECT IN의 성능을 향상시킬 수있는 몇 가지 방법입니다. http://florianreischl.blogspot.ca/2012/03/performance-comparison-of-sql-server.html – Henry