Sql Server 2008:如何最小化存储过程的执行时间

Sql Server 2008:如何最小化存储过程的执行时间,sql,sql-server,sql-server-2008,stored-procedures,Sql,Sql Server,Sql Server 2008,Stored Procedures,我有Sql Server数据库,我的表有1500000行…因为数据量很大 我的以下程序的执行时间非常长 桌子--- CREATE TABLE [dbo].[MyTable]( [Id] [bigint] IDENTITY(1,1) NOT NULL, [Link] [text] NULL, [Title] [text] NULL, [Duration] [text] NULL, [Image] [text] NULL, [Embbed] [text] NULL, [Keywords] [text

我有Sql Server数据库,我的表有1500000行…因为数据量很大 我的以下程序的执行时间非常长

桌子---

CREATE TABLE [dbo].[MyTable](
[Id] [bigint] IDENTITY(1,1) NOT NULL,
[Link] [text] NULL,
[Title] [text] NULL,
[Duration] [text] NULL,
[Image] [text] NULL,
[Embbed] [text] NULL,
[Keywords] [text] NULL,
[Category] [text] NULL,
PRIMARY KEY CLUSTERED 
(
[Id] ASC
)
WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
程序---

ALTER PROCEDURE [dbo].[Search]
 @SearchQuery varchar(1000),
 @Id bigint
 As
BEGIN
  Select top 100 * from MyTable
  where Id > @Id and Title like '%'+@SearchQuery+'%'
有谁能帮我最大限度地减少1500000行表上sql查询的执行时间吗?

问题类似于WHERE子句。您正在搜索字段中任何位置的文本,这会导致标题列上可能存在的索引未被使用

只要你需要像“%…”那样在字段中间搜索使用术语,很可能没有机会优化查询运行时间。

即使查询引擎本身应该足够智能,您也可以尝试执行以下操作:

将ID为>@ID的条目选择到临时表中,然后使用LIKE语句从该表中选择前100名。

问题在于WHERE子句中的LIKE。您正在搜索字段中任何位置的文本,这会导致标题列上可能存在的索引未被使用

只要你需要像“%…”那样在字段中间搜索使用术语,很可能没有机会优化查询运行时间。

即使查询引擎本身应该足够智能,您也可以尝试执行以下操作:


将ID为>@ID的条目选择到临时表中,然后使用LIKE语句从该表中选择前100名。

发布您的表定义,这将帮助我们帮助您。但是,您可以检查以下几点:

确保表具有主键和聚集索引。它们的定义几乎无关紧要,只要它们存在。我建议在没有任何其他信息的情况下,在Id上定义它们

您真的需要返回表中的所有列吗?如果有很多列,而您只需要很少的列,那么显式地指定它们。这将减少结果集的大小

询问用户是否真的有必要对标题进行包含搜索。您是否可以改为以搜索开始,即删除第一个“%”而不受影响?如果可以这样做,那么标题过滤器将变得可搜索,即查询优化器将使用标题列上的索引,而不是执行表扫描。你确实有一个标题索引,不是吗

更新:

看过表定义后,我注意到标题有文本类型。使用表扫描进行搜索的速度非常慢,因为所有数据都存储在表行之外,必须单独获取。您可以通过将其更改为varchar类型来加快速度。文本的现代等价物是varcharmax,所以请先尝试一下。但是,由于它是一个标题,您确定您真的需要在列中包含2GB的字符吗?大多数事物的标题最多不超过100个字符。试着测量一下你所有标题的长度,看看你是否能把专栏的长度缩短到更合理的长度


事实上,看看你所有栏目的名称,我看不出有任何理由使用文本。即使是我假设是URL的链接,也只需要varchar1023。

发布您的表定义,这将帮助我们帮助您。但是,您可以检查以下几点:

确保表具有主键和聚集索引。它们的定义几乎无关紧要,只要它们存在。我建议在没有任何其他信息的情况下,在Id上定义它们

您真的需要返回表中的所有列吗?如果有很多列,而您只需要很少的列,那么显式地指定它们。这将减少结果集的大小

询问用户是否真的有必要对标题进行包含搜索。您是否可以改为以搜索开始,即删除第一个“%”而不受影响?如果可以这样做,那么标题过滤器将变得可搜索,即查询优化器将使用标题列上的索引,而不是执行表扫描。你确实有一个标题索引,不是吗

更新:

看过表定义后,我注意到标题有文本类型。使用表扫描进行搜索的速度非常慢,因为所有数据都存储在表行之外,必须单独获取。您可以通过将其更改为varchar类型来加快速度。文本的现代等价物是varcharmax,所以请先尝试一下。但是,由于它是一个标题,您确定您真的需要在列中包含2GB的字符吗?大多数事物的标题最多不超过100个字符。试着测量一下你所有标题的长度,看看你是否能把专栏的长度缩短到更合理的长度

事实上,看看你所有栏目的名称,我看不出有任何理由使用文本。即使是我假定为URL的链接,也只需要varchar1023即可 通过以下方式扫描表格:

标题类似“%”++@SearchQuery++“%”

事实上,没有-你强制绝对不在标题上使用索引。当索引从左到右时,中间查询的某个点只会关闭索引使用。

如果ID留下了很多要搜索的内容,那你就去吧,尤其是当你把它与速度不适当的硬件结合在一起时,毕竟150万都是小数据


您可以删除LIKE语句中的第一个%(因此可以使用索引),也可以使用全文搜索,这将已经分解索引中的单词,但即使如此,您最好删除第一个%。

您可以通过以下方式强制表扫描:

标题类似“%”++@SearchQuery++“%”

事实上,没有-你强制绝对不在标题上使用索引。当索引从左到右时,中间查询的某个点只会关闭索引使用。

如果ID留下了很多要搜索的内容,那你就去吧,尤其是当你把它与速度不适当的硬件结合在一起时,毕竟150万都是小数据

你要么去掉LIKE语句中的第一个%(这样就可以使用索引),要么使用全文搜索,这将已经分解索引中的单词,但即使这样,你最好去掉第一个%。

我将把你的LIKE语句改为CharIndex,正如其他人所说的那样,LIKE将导致对表的完全扫描

向您展示如何使用CHARINDEX

我想将您的LIKE语句更改为CHARINDEX,因为其他人说LIKE将导致表的完整扫描

向您展示如何使用CHARINDEX

使用VARCHARMAX而不是文本作为字段类型

文本字段存储在表其余部分的单独位置,而VARCHARMAX字段与行数据一起存储,因此可以对此类字段应用全文索引。

使用VARCHARMAX而不是文本作为字段类型



文本字段存储在表其余部分的单独位置,而VARCHARMAX字段与行数据一起存储,因此可以对此类字段应用全文索引。

这一个仍然打开吗?将文本字段更改为varchar并添加set rowcount语句后,如果需要保留主要的通配符功能,那么就在sql中完成了所有可以做的事情。我经常做这类事情,没有性能问题,所以下一步就是:硬件升级。

这一步还开着吗?将文本字段更改为varchar并添加set rowcount语句后,如果需要保留主要的通配符功能,那么就在sql中完成了所有可以做的事情。我经常做这类事情,没有性能问题,所以下一步是:硬件升级。

能否为MyTable提供create table语句,包括其上的潜在索引。是否需要使用select*,是否可以替换为列列表?你的表有索引吗?150万行是很小的——你知道,这更多的是一个非智能SQL的问题。但不要说这是大量数据-我处理十亿行数据库。是的,我的表有索引…我需要*…但我可以用column name替换它。是的,TomTomTom你是对的,它是小数据…。你能为我的表提供create table语句吗?包括表上的潜在索引。你需要使用select*,可以用列列表替换吗?你的表有索引吗?150万行是很小的——你知道,这更多的是一个非智能SQL的问题。但不要说这是大量数据-我处理的是十亿行数据库。是的,我的表有索引…我需要*…但我可以用Column名称替换它是tomtom你是对的,它是小数据…只要你需要以这种方式使用LIKE搜索,就应该读取-你可以使用LIKE并使用索引,只是在学期前没有一个百分点。修正了这一点-我很清楚,但是我没有正确地写下来:-这就是投票失败的原因吗?实际上我使用了一个临时表..但现在的问题是当搜索查询没有结果时..这将花费太多的时间..应该阅读,只要你需要以这种方式使用LIKE进行搜索-你可以使用LIKE并使用索引,只是在学期前没有一个百分点。修正了这一点-我很清楚,但是我没有正确地写下来:-这就是否决投票的原因吗?实际上我使用了一个临时表..但现在的问题是当搜索查询没有结果时..这将花费很多时间..CHARINDEX也不可搜索,因此也不会阻止完全扫描问题。CHARINDEX也不可搜索,所以也不会防止完全扫描问题。原则上,OP应该避免使用不推荐的数据类型,但我很确定文本可以被全文索引。FTS在SQL Server 2005之前引入了MAX数据类型。您确实是对的,可以对这两种字段类型应用全文索引。在本例中,我将使用VARCHARMAX,应用全文索引,并使用CONTAINS,而不是OP应该使用的原则点
oid是不推荐使用的数据类型,但我非常确定文本可以被全文索引。FTS在SQL Server 2005之前引入了MAX数据类型。您确实是对的,可以对这两种字段类型应用全文索引。在本例中,我将使用VARCHARMAX,应用全文索引,并使用CONTAINS而不是LIKE