我有一个AJAX快速搜索功能,用户可在其中搜索目录中的名称。查询看起来像这样,其中name是参数:
SELECT TOP 30 *
FROM CONTACT c
WHERE ( c.FIRST_NAME LIKE '%#name#%'
OR c.LAST_NAME LIKE '%#name#%' )
OR ( c.FIRST_NAME + ' ' + c.LAST_NAME LIKE '%#name#%' )
OR ( c.LAST_NAME + ' ' + c.FIRST_NAME LIKE '%#name#%' )
ORDER BY LAST_NAME,
FIRST_NAME
支持此类查询的最佳索引类型是什么?或者我应该以不同方式构建查询以优化性能?任何建议都会很棒。
答案 0 :(得分:0)
我认为你最好的选择是:
查看您的查询计划,看看是否存在问题。如果很难理解提问或在这里查看:http://www.mssqltips.com/sqlservertip/1873/how-to-read-sql-server-graphical-query-execution-plans/
查看sys.dm_db_missing_index_details表中的数据库本身,查看是否缺少索引并按照此处所述评估建议:http://www.danielahill.com/Blog/SQL_Server_Find_Add_Missing_Indexes.aspx
查看SQL Server计算机本身的性能(cpu低,磁盘活动低)
查看应用程序的性能
我认为查询的性能根据其中的数据以及数据库缓存信息的容易程度而有很大差异,并且很难提供大量具体建议。
答案 1 :(得分:0)
作为起点,您可以尝试:
create index IX_CONTACT_Last_First on CONTACT (LAST_NAME, FIRST_NAME);
虽然使用like
(与完全匹配条件相比)可能没有太大的好处,但如果表中有很多其他列,至少它可能有帮助扫描较少的数据页面。
如果*
实际只需要部分列,则不应使用*
,并且应直接指定必要的列(例如select top (30) ID, LAST_NAME, FIRST_NAME, PHONE, EMAIL from ...
),您可以尝试将它们包含在索引中:
create index IX_CONTACT_Last_First on CONTACT (LAST_NAME, FIRST_NAME)
include (PHONE, EMAIL, ID);
另外,我不确定,但似乎where
子句中的某些条件是多余的,您可以尝试少检查:
SELECT TOP (30) FIRST_NAME, LAST_NAME
FROM CONTACT c
WHERE ( c.FIRST_NAME + ' ' + c.LAST_NAME LIKE '%#name#%' )
OR ( c.LAST_NAME + ' ' + c.FIRST_NAME LIKE '%#name#%' )
ORDER BY LAST_NAME, FIRST_NAME;