即使使用非聚集索引和全文索引,SE​​LECT 查询也很慢

Bla*_*olf 8 sql-server stored-procedures t-sql sql-server-2014

我试图从表中查询 0 到 65,000 行。

服务器使用的是Microsoft SQL Server 2014,我无法更改服务器上的硬件。

架构

[Id] (PK)        INT      
[varchar1]  VARCHAR(4)     Normal Cardinality
[varchar2]  VARCHAR(250)   Normal Cardinality
[varchar3]  VARCHAR(250)   Normal Cardinality
[varchar4]  VARCHAR(100)   Normal Cardinality
[date1]     DATETIME       High Cardinality
[varchar5]  VARCHAR(100)   Low Cardinality
[varchar6]  VARCHAR(1000)  Normal Cardinality
[varchar7]  VARCHAR(100)   Normal Cardinality
[varchar8]  VARCHAR(20)    Normal Cardinality
[varchar9]  VARCHAR(100)   High Cardinality
[xml1]      XML            Low Cardinality
Run Code Online (Sandbox Code Playgroud)

询问

以下查询是存储过程的一部分(其余部分无关紧要,因为它对存储过程的性能影响不大)。列名称已替换为列类型和编号:

SELECT   [varchar1]
       , [varchar4]
       , [date1]
       , [varchar5]
       , [varchar6]
       , [varchar7]
       , [varchar8]
       , [varchar9]
       , [xml1]
FROM [database].[dbo].[table] WITH (NOLOCK)
WHERE [varchar1] = '0'
AND   ([date1] >='2014-1-1' AND [date1] <= '2017-1-1')
AND   [varchar8] = 'someText'
AND   [varchar9] LIKE '%a%'
ORDER BY [varchar1] ASC, [date1] DESC
OFFSET 0 ROWS
FETCH NEXT 65000 ROWS ONLY
Run Code Online (Sandbox Code Playgroud)

执行计划

执行计划 XML:https : //gist.github.com/BlackyWolf/046856518065bfe5293cad78f73340e9

但到目前为止它提供的信息是:

Query1: Query cost (relative to the batch): 100%
                               Index Seek [NonClustered]
 SELECT            Top          [Table].[i_table_index]
Cost: 0%         Cost: 4%              Cost: 96%
Run Code Online (Sandbox Code Playgroud)

执行计划声明

我没有在此搜索中使用 PK。此查询具有以下持续时间,具体取决于删除的列:

select 语句中的所有列 = 18s-27s
没有 [xml1] = 8s-11s
没有 [xml1] 和 [varchar4] = 4s-6s

从 Web 到 DB 再返回的总执行时间需要在 10 秒内。最好这个查询需要在 4s 之内。

返回大小 (MB)

我希望返回价值 290-310 MB 的数据,误差幅度为 20 MB,总共 65,000 条记录。

指数

主键上有一个聚集索引。

有一个非聚集索引定义为:

CREATE NONCLUSTERED INDEX [i_table_index]
ON dbo.[table] ([varchar1], [date1] DESC, [varchar8], [varchar9])
INCLUDE ([varchar4], [varchar7], [xml1]);
Run Code Online (Sandbox Code Playgroud)

不幸的是,我无法真正删除[xml1][varchar4]或我会。说实话,索引似乎没有多大帮助,即使执行计划显示它正在使用它。

我的 SQL 经验仅限于我使用 C# 所做的事情。感谢您提供的任何帮助或指导(甚至是链接),如果您需要更多信息,请告诉我,我会尽力获取。

小智 1

where 子句中的每个元素都使用函数。当使用函数时,sql无法确定使用什么索引。它无法确定 where 子句中的哪些字段导致表扫描。

  1. 将日期收敛到 date => 和 date =<
  2. 数据库真的区分大小写吗?你能去掉lower()吗
  3. 你能把 contains 变成 patindex 吗

  • 我按照你所说的执行计划从索引扫描(之前执行的操作)更改为索引查找(仍然没有加速)。我确实将包含更改为 padindex,但它也没有影响持续时间的查询。 (2认同)