Need assistance optimizing ColdFusion query pulling data from several tables
I wrote a query that my db admins are telling me need optimized, but my SQL knowledge is limited. The query pulls the press releases and 1 related photo and caption for each. It joins the site (location) table on id.
<cfquery name="local.query" datasource="#this.Dsn()#">
SELECT
pr.press_release_id,
pr.Site_id,
pr.press_release_subject,
pr.press_release_title,
pr.press_release_datetime,
pr.press_release_number,
pr.press_release_published_flag,
pr.press_release_top_story,
pr.related_photo_gallery,
pr.related_page,
s.site_name,
(SELECT TOP 1 ph.press_release_photo_lowres_filename
FROM
tbl_photo as ph
WHERE
ph.press_release_id = pr.press_release_id) as photo_filename,
(SELECT TOP 1 ph.press_release_photo_caption
FROM
tbl_photo as ph
WHERE
ph.press_release_id = pr.press_release_id) as photo_caption
FROM
tbl_press_release as pr
INNER JOIN tbl_site s
ON pr.Site_id = s.site_id
WHERE
LEFT(pr.press_release_number,1) <> <cfqueryparam cfsqltype="cf_sql_varchar" value="I">
<cfif val(event.GetValue("site_id")) gt 0>
AND s.site_id = <cfqueryparam cfsqltype="cf_sql_integer" value="#val(event.GetValue("site_id"))#">
</cfif>
<cfif event.GetValue("pao_search") neq "">
AND
(
press_release_subject like <cfqueryparam cfsqltype="cf_sql_varchar" value="%#event.GetValue("pao_search")#%">
OR
press_release_copy like <cfqueryparam cfsqltype="cf_sql_varchar" value="%#event.GetValue("pao_search")#%">
OR
press_release_wingspan_title like <cfqueryparam cfsqltype="cf_sql_varchar" value="%#event.GetValue("pao_search")#%">
OR
press_release_wingspan_subject like <cfqueryparam cfsqltype="cf_sql_varchar" value="%#event.GetValue("pao_search")#%">
)
</cfif>
AND pr.press_release_published_flag = <cfqueryparam cfsqltype="cf_sql_integer" value="1">
AND (pr.press_release_top_story <> <cfqueryparam cfsqltype="cf_sql_bit" value="True"> OR pr.press_release_top_story IS NULL)
<cfi开发者_C百科f listLen(event.GetValue("orderBy")) neq 0>
ORDER BY
<cfloop list="#event.GetValue("orderBy")#" index="local.o">#local.o# #uCase(event.GetValue("sort"))#<cfif local.o neq listLast(event.GetValue("orderBy"))>,</cfif></cfloop>
</cfif>
</cfquery>
From what the admins told me, the embedded SELECT statements are slowing the query down. I realize now that pulling associated images and captions for every press release is unnecessary since I only need to pull them for press releases with press_release_top_story that equals true. I think that might help save some CPU as well.
What can I do to optimize this? FYI this is for SQL Server is that matters.
First and foremost, consider caching. ColdFusion can easily cache queries (e.g. <cfquery cachedWithin="#createTimeSpan(d, h, m, s)#">...</cfquery>
, but if you need to ensure timeliness when the underlying press release table updates, instead use cachePut()
and cacheGet()
, where values are put in when the press release table is updated.
Next, the WHERE clause LIKE statements are probably the culprit for the slowdown: two approaches to consider are a SQL Server full text index or using ColdFusion's search capabilities. In addition, use SQL Server's database tuning advisor on the query to see if there are other indices that will improve performance.
I think orangepips is probably right regarding the LIKE statements being the culprit, and not the subselects.
One thing you can do as a quick and dirty way to see if sql server can suggest improvements, is to copy the query into management studio, run it to ensure it works, and then right click in the editor and select "Analyze query in database engine tuning advisor". Go through that process, and it'll at least find any obvious missing indexes.
精彩评论