Поиск в текстовом столбце по ключевым словам очень медленный

У меня есть база данных SQL Server, в которой есть только одна таблица с несколькими столбцами. В настоящее время существует несколько тысяч строк. Столбцы следующие:

id (nvarchar(35))
path (nvarchar(255))
body (ntext)
datetimecreated (datetime)
author (nvarchar(255))
version (int)
summary (nvarchar(255))

Поисковый запрос следующий:

SELECT [id],[path],[body],[datetimecreated],[author],[version],[summary]
  FROM [dbo].[pages] p1
  where     ([version] =
                  (select     max(p2.[version])
                   from          [dbo].[pages] p2
                   where      p1.[path] = p2.[path]))       
and (body like '%outlook%'
or summary like '%outlook%'
or author like '%outlook%'
)
order by   p1.[path] asc

Поиск, подобный приведенному выше, займет 8-10 секунд. Я пробовал скопировать базу данных и преобразовать ntext в nvarchar(max) и не вижу разницы во времени запроса. Я также попытался создать полнотекстовый индекс и выполнить поиск по следующему:

contains (body, '"outlook"') or CONTAINS (summary, '"outlook"')

На самом деле это занимает больше времени.

Мне нужен совет/помощь, чтобы ускорить поисковые запросы. Я не проектировал базу данных.

Я попытался изменить столбец body на nvarchar(max) и создать полнотекстовый индекс, но безрезультатно.

Вот план выполнения:

<?xml version = "1.0" encoding = "utf-16"?>
<ShowPlanXML xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd = "http://www.w3.org/2001/XMLSchema" Version = "1.589" Build = "16.0.5564.30211" xmlns = "http://schemas.microsoft.com/sqlserver/2004/07/showplan">
  <BatchSequence>
    <Batch>
      <Statements>
        <StmtSimple StatementCompId = "1" StatementEstRows = "1" StatementId = "1" StatementOptmLevel = "FULL" CardinalityEstimationModelVersion = "120" StatementSubTreeCost = "1.90059" StatementText = "SELECT TOP 1000 [id]&#xD;&#xA;      ,[path]&#xD;&#xA;      ,[body]&#xD;&#xA;      ,[datetimecreated]&#xD;&#xA;      ,[author]&#xD;&#xA;      ,[version]&#xD;&#xA;      ,[summary]&#xD;&#xA;  FROM [dbo].[pages_1] p1&#xD;&#xA;  where     ([version] =&#xD;&#xA;                  (select     max(p2.[version])&#xD;&#xA;                   from          [dbo].[pages_1] p2&#xD;&#xA;                   where      p1.[path] = p2.[path]))        &#xD;&#xA;and (body like '%outlook%'&#xD;&#xA;or summary like '%outlook%'&#xD;&#xA;/*or author like '%outlook%'*/&#xD;&#xA;)&#xD;&#xA;order by   p1.[path] asc" StatementType = "SELECT" QueryHash = "0x91AAE73160CEF12C" QueryPlanHash = "0xE33814DCBC42ED0F" RetrievedFromCache = "true" StatementSqlHandle = "0x09003CE69250B7708CCD87CBDE6C4A7A08DE0000000000000000000000000000000000000000000000000000" DatabaseContextSettingsId = "12" ParentObjectId = "0" StatementParameterizationType = "0" SecurityPolicyApplied = "false">
          <StatementSetOptions ANSI_NULLS = "true" ANSI_PADDING = "true" ANSI_WARNINGS = "true" ARITHABORT = "true" CONCAT_NULL_YIELDS_NULL = "true" NUMERIC_ROUNDABORT = "false" QUOTED_IDENTIFIER = "true" />
          <QueryPlan DegreeOfParallelism = "1" MemoryGrant = "1424" CachedPlanSize = "48" CompileTime = "399" CompileCPU = "63" CompileMemory = "512">
            <MemoryGrantInfo SerialRequiredMemory = "640" SerialDesiredMemory = "1424" RequiredMemory = "640" DesiredMemory = "1424" RequestedMemory = "1424" GrantWaitTime = "0" GrantedMemory = "1424" MaxUsedMemory = "520" MaxQueryMemory = "401408" />
            <OptimizerHardwareDependentProperties EstimatedAvailableMemoryGrant = "47815008" EstimatedPagesCached = "5976876" EstimatedAvailableDegreeOfParallelism = "2" MaxCompileMemory = "1349624" />
            <RelOp AvgRowSize = "4855" EstimateCPU = "1E-07" EstimateIO = "0" EstimateRebinds = "0" EstimateRewinds = "0" EstimatedExecutionMode = "Row" EstimateRows = "1" LogicalOp = "Top" NodeId = "0" Parallel = "false" PhysicalOp = "Top" EstimatedTotalSubtreeCost = "1.90059">
              <OutputList>
                <ColumnReference Database = "[wiki]" Schema = "[dbo]" Table = "[pages_1]" Alias = "[p1]" Column = "id" />
                <ColumnReference Database = "[wiki]" Schema = "[dbo]" Table = "[pages_1]" Alias = "[p1]" Column = "path" />
                <ColumnReference Database = "[wiki]" Schema = "[dbo]" Table = "[pages_1]" Alias = "[p1]" Column = "body" />
                <ColumnReference Database = "[wiki]" Schema = "[dbo]" Table = "[pages_1]" Alias = "[p1]" Column = "datetimecreated" />
                <ColumnReference Database = "[wiki]" Schema = "[dbo]" Table = "[pages_1]" Alias = "[p1]" Column = "author" />
                <ColumnReference Database = "[wiki]" Schema = "[dbo]" Table = "[pages_1]" Alias = "[p1]" Column = "version" />
                <ColumnReference Database = "[wiki]" Schema = "[dbo]" Table = "[pages_1]" Alias = "[p1]" Column = "summary" />
              </OutputList>
              <RunTimeInformation>
                <RunTimeCountersPerThread Thread = "0" ActualRows = "4" Batches = "0" ActualEndOfScans = "1" ActualExecutions = "1" ActualExecutionMode = "Row" ActualElapsedms = "8595" ActualCPUms = "701" />
              </RunTimeInformation>
              <Top RowCount = "false" IsPercent = "false" WithTies = "false">
                <TopExpression>
                  <ScalarOperator ScalarString = "(1000)">
                    <Const ConstValue = "(1000)" />
                  </ScalarOperator>
                </TopExpression>
                <RelOp AvgRowSize = "4855" EstimateCPU = "0.00586661" EstimateIO = "0" EstimateRebinds = "0" EstimateRewinds = "0" EstimatedExecutionMode = "Row" EstimateRows = "1" LogicalOp = "Inner Join" NodeId = "1" Parallel = "false" PhysicalOp = "Merge Join" EstimatedTotalSubtreeCost = "1.90059">
                  <OutputList>
                    <ColumnReference Database = "[wiki]" Schema = "[dbo]" Table = "[pages_1]" Alias = "[p1]" Column = "id" />
                    <ColumnReference Database = "[wiki]" Schema = "[dbo]" Table = "[pages_1]" Alias = "[p1]" Column = "path" />
                    <ColumnReference Database = "[wiki]" Schema = "[dbo]" Table = "[pages_1]" Alias = "[p1]" Column = "body" />
                    <ColumnReference Database = "[wiki]" Schema = "[dbo]" Table = "[pages_1]" Alias = "[p1]" Column = "datetimecreated" />
                    <ColumnReference Database = "[wiki]" Schema = "[dbo]" Table = "[pages_1]" Alias = "[p1]" Column = "author" />
                    <ColumnReference Database = "[wiki]" Schema = "[dbo]" Table = "[pages_1]" Alias = "[p1]" Column = "version" />
                    <ColumnReference Database = "[wiki]" Schema = "[dbo]" Table = "[pages_1]" Alias = "[p1]" Column = "summary" />
                  </OutputList>
                  <RunTimeInformation>
                    <RunTimeCountersPerThread Thread = "0" ActualRows = "4" Batches = "0" ActualEndOfScans = "1" ActualExecutions = "1" ActualExecutionMode = "Row" ActualElapsedms = "8595" ActualCPUms = "701" ActualScans = "0" ActualLogicalReads = "0" ActualPhysicalReads = "0" ActualReadAheads = "0" ActualLobLogicalReads = "0" ActualLobPhysicalReads = "0" ActualLobReadAheads = "0" />
                  </RunTimeInformation>
                  <Merge ManyToMany = "false">
                    <InnerSideJoinColumns>
                      <ColumnReference Database = "[wiki]" Schema = "[dbo]" Table = "[pages_1]" Alias = "[p1]" Column = "path" />
                    </InnerSideJoinColumns>
                    <OuterSideJoinColumns>
                      <ColumnReference Database = "[wiki]" Schema = "[dbo]" Table = "[pages_1]" Alias = "[p2]" Column = "path" />
                    </OuterSideJoinColumns>
                    <Residual>
                      <ScalarOperator ScalarString = "[Expr1002]=[wiki].[dbo].[pages_1].[version] as [p1].[version] AND [wiki].[dbo].[pages_1].[path] as [p2].[path]=[wiki].[dbo].[pages_1].[path] as [p1].[path]">
                        <Logical Operation = "AND">
                          <ScalarOperator>
                            <Compare CompareOp = "EQ">
                              <ScalarOperator>
                                <Identifier>
                                  <ColumnReference Column = "Expr1002" />
                                </Identifier>
                              </ScalarOperator>
                              <ScalarOperator>
                                <Identifier>
                                  <ColumnReference Database = "[wiki]" Schema = "[dbo]" Table = "[pages_1]" Alias = "[p1]" Column = "version" />
                                </Identifier>
                              </ScalarOperator>
                            </Compare>
                          </ScalarOperator>
                          <ScalarOperator>
                            <Compare CompareOp = "EQ">
                              <ScalarOperator>
                                <Identifier>
                                  <ColumnReference Database = "[wiki]" Schema = "[dbo]" Table = "[pages_1]" Alias = "[p2]" Column = "path" />
                                </Identifier>
                              </ScalarOperator>
                              <ScalarOperator>
                                <Identifier>
                                  <ColumnReference Database = "[wiki]" Schema = "[dbo]" Table = "[pages_1]" Alias = "[p1]" Column = "path" />
                                </Identifier>
                              </ScalarOperator>
                            </Compare>
                          </ScalarOperator>
                        </Logical>
                      </ScalarOperator>
                    </Residual>
                    <RelOp AvgRowSize = "65" EstimateCPU = "0.0016498" EstimateIO = "0" EstimateRebinds = "0" EstimateRewinds = "0" EstimatedExecutionMode = "Row" EstimateRows = "98" LogicalOp = "Aggregate" NodeId = "2" Parallel = "false" PhysicalOp = "Stream Aggregate" EstimatedTotalSubtreeCost = "0.969562">
                      <OutputList>
                        <ColumnReference Database = "[wiki]" Schema = "[dbo]" Table = "[pages_1]" Alias = "[p2]" Column = "path" />
                        <ColumnReference Column = "Expr1002" />
                      </OutputList>
                      <RunTimeInformation>
                        <RunTimeCountersPerThread Thread = "0" ActualRows = "98" Batches = "0" ActualEndOfScans = "1" ActualExecutions = "1" ActualExecutionMode = "Row" ActualElapsedms = "3" ActualCPUms = "3" />
                      </RunTimeInformation>
                      <StreamAggregate>
                        <DefinedValues>
                          <DefinedValue>
                            <ColumnReference Column = "Expr1002" />
                            <ScalarOperator ScalarString = "MAX([wiki].[dbo].[pages_1].[version] as [p2].[version])">
                              <Aggregate AggType = "MAX" Distinct = "false">
                                <ScalarOperator>
                                  <Identifier>
                                    <ColumnReference Database = "[wiki]" Schema = "[dbo]" Table = "[pages_1]" Alias = "[p2]" Column = "version" />
                                  </Identifier>
                                </ScalarOperator>
                              </Aggregate>
                            </ScalarOperator>
                          </DefinedValue>
                        </DefinedValues>
                        <GroupBy>
                          <ColumnReference Database = "[wiki]" Schema = "[dbo]" Table = "[pages_1]" Alias = "[p2]" Column = "path" />
                        </GroupBy>
                        <RelOp AvgRowSize = "65" EstimateCPU = "0.047471" EstimateIO = "0.0112613" EstimateRebinds = "0" EstimateRewinds = "0" EstimatedExecutionMode = "Row" EstimateRows = "2668" LogicalOp = "Sort" NodeId = "3" Parallel = "false" PhysicalOp = "Sort" EstimatedTotalSubtreeCost = "0.967912">
                          <OutputList>
                            <ColumnReference Database = "[wiki]" Schema = "[dbo]" Table = "[pages_1]" Alias = "[p2]" Column = "path" />
                            <ColumnReference Database = "[wiki]" Schema = "[dbo]" Table = "[pages_1]" Alias = "[p2]" Column = "version" />
                          </OutputList>
                          <MemoryFractions Input = "1" Output = "0.734694" />
                          <RunTimeInformation>
                            <RunTimeCountersPerThread Thread = "0" ActualRebinds = "1" ActualRewinds = "0" ActualRows = "2668" Batches = "0" ActualEndOfScans = "1" ActualExecutions = "1" ActualExecutionMode = "Row" ActualElapsedms = "3" ActualCPUms = "3" ActualScans = "0" ActualLogicalReads = "0" ActualPhysicalReads = "0" ActualReadAheads = "0" ActualLobLogicalReads = "0" ActualLobPhysicalReads = "0" ActualLobReadAheads = "0" InputMemoryGrant = "1296" OutputMemoryGrant = "704" UsedMemoryGrant = "280" />
                          </RunTimeInformation>
                          <Sort Distinct = "false">
                            <OrderBy>
                              <OrderByColumn Ascending = "true">
                                <ColumnReference Database = "[wiki]" Schema = "[dbo]" Table = "[pages_1]" Alias = "[p2]" Column = "path" />
                              </OrderByColumn>
                            </OrderBy>
                            <RelOp AvgRowSize = "65" EstimateCPU = "0.0030918" EstimateIO = "0.906088" EstimateRebinds = "0" EstimateRewinds = "0" EstimatedExecutionMode = "Row" EstimateRows = "2668" LogicalOp = "Clustered Index Scan" NodeId = "4" Parallel = "false" PhysicalOp = "Clustered Index Scan" EstimatedTotalSubtreeCost = "0.90918" TableCardinality = "2668">
                              <OutputList>
                                <ColumnReference Database = "[wiki]" Schema = "[dbo]" Table = "[pages_1]" Alias = "[p2]" Column = "path" />
                                <ColumnReference Database = "[wiki]" Schema = "[dbo]" Table = "[pages_1]" Alias = "[p2]" Column = "version" />
                              </OutputList>
                              <RunTimeInformation>
                                <RunTimeCountersPerThread Thread = "0" ActualRows = "2668" ActualRowsRead = "2668" Batches = "0" ActualEndOfScans = "1" ActualExecutions = "1" ActualExecutionMode = "Row" ActualElapsedms = "1" ActualCPUms = "1" ActualScans = "1" ActualLogicalReads = "1247" ActualPhysicalReads = "0" ActualReadAheads = "0" ActualLobLogicalReads = "0" ActualLobPhysicalReads = "0" ActualLobReadAheads = "0" />
                              </RunTimeInformation>
                              <IndexScan Ordered = "false" ForcedIndex = "false" ForceScan = "false" NoExpandHint = "false" Storage = "RowStore">
                                <DefinedValues>
                                  <DefinedValue>
                                    <ColumnReference Database = "[wiki]" Schema = "[dbo]" Table = "[pages_1]" Alias = "[p2]" Column = "path" />
                                  </DefinedValue>
                                  <DefinedValue>
                                    <ColumnReference Database = "[wiki]" Schema = "[dbo]" Table = "[pages_1]" Alias = "[p2]" Column = "version" />
                                  </DefinedValue>
                                </DefinedValues>
                                <Object Database = "[wiki]" Schema = "[dbo]" Table = "[pages_1]" Index = "[PK_pages_1]" Alias = "[p2]" IndexKind = "Clustered" Storage = "RowStore" />
                              </IndexScan>
                            </RelOp>
                          </Sort>
                        </RelOp>
                      </StreamAggregate>
                    </RelOp>
                    <RelOp AvgRowSize = "4855" EstimateCPU = "0.000235967" EstimateIO = "0.0112613" EstimateRebinds = "0" EstimateRewinds = "0" EstimatedExecutionMode = "Row" EstimateRows = "19.5838" LogicalOp = "Sort" NodeId = "5" Parallel = "false" PhysicalOp = "Sort" EstimatedTotalSubtreeCost = "0.925159">
                      <OutputList>
                        <ColumnReference Database = "[wiki]" Schema = "[dbo]" Table = "[pages_1]" Alias = "[p1]" Column = "id" />
                        <ColumnReference Database = "[wiki]" Schema = "[dbo]" Table = "[pages_1]" Alias = "[p1]" Column = "path" />
                        <ColumnReference Database = "[wiki]" Schema = "[dbo]" Table = "[pages_1]" Alias = "[p1]" Column = "body" />
                        <ColumnReference Database = "[wiki]" Schema = "[dbo]" Table = "[pages_1]" Alias = "[p1]" Column = "datetimecreated" />
                        <ColumnReference Database = "[wiki]" Schema = "[dbo]" Table = "[pages_1]" Alias = "[p1]" Column = "author" />
                        <ColumnReference Database = "[wiki]" Schema = "[dbo]" Table = "[pages_1]" Alias = "[p1]" Column = "version" />
                        <ColumnReference Database = "[wiki]" Schema = "[dbo]" Table = "[pages_1]" Alias = "[p1]" Column = "summary" />
                      </OutputList>
                      <MemoryFractions Input = "0.265306" Output = "0.265306" />
                      <RunTimeInformation>
                        <RunTimeCountersPerThread Thread = "0" ActualRebinds = "1" ActualRewinds = "0" ActualRows = "79" Batches = "0" ActualEndOfScans = "1" ActualExecutions = "1" ActualExecutionMode = "Row" ActualElapsedms = "8592" ActualCPUms = "697" ActualScans = "0" ActualLogicalReads = "0" ActualPhysicalReads = "0" ActualReadAheads = "0" ActualLobLogicalReads = "0" ActualLobPhysicalReads = "0" ActualLobReadAheads = "0" InputMemoryGrant = "712" OutputMemoryGrant = "328" UsedMemoryGrant = "240" />
                      </RunTimeInformation>
                      <Sort Distinct = "false">
                        <OrderBy>
                          <OrderByColumn Ascending = "true">
                            <ColumnReference Database = "[wiki]" Schema = "[dbo]" Table = "[pages_1]" Alias = "[p1]" Column = "path" />
                          </OrderByColumn>
                        </OrderBy>
                        <RelOp AvgRowSize = "4855" EstimateCPU = "0.00448224" EstimateIO = "0" EstimateRebinds = "0" EstimateRewinds = "0" EstimatedExecutionMode = "Row" EstimateRows = "19.5838" LogicalOp = "Filter" NodeId = "6" Parallel = "false" PhysicalOp = "Filter" EstimatedTotalSubtreeCost = "0.913662">
                          <OutputList>
                            <ColumnReference Database = "[wiki]" Schema = "[dbo]" Table = "[pages_1]" Alias = "[p1]" Column = "id" />
                            <ColumnReference Database = "[wiki]" Schema = "[dbo]" Table = "[pages_1]" Alias = "[p1]" Column = "path" />
                            <ColumnReference Database = "[wiki]" Schema = "[dbo]" Table = "[pages_1]" Alias = "[p1]" Column = "body" />
                            <ColumnReference Database = "[wiki]" Schema = "[dbo]" Table = "[pages_1]" Alias = "[p1]" Column = "datetimecreated" />
                            <ColumnReference Database = "[wiki]" Schema = "[dbo]" Table = "[pages_1]" Alias = "[p1]" Column = "author" />
                            <ColumnReference Database = "[wiki]" Schema = "[dbo]" Table = "[pages_1]" Alias = "[p1]" Column = "version" />
                            <ColumnReference Database = "[wiki]" Schema = "[dbo]" Table = "[pages_1]" Alias = "[p1]" Column = "summary" />
                          </OutputList>
                          <RunTimeInformation>
                            <RunTimeCountersPerThread Thread = "0" ActualRows = "79" Batches = "0" ActualEndOfScans = "1" ActualExecutions = "1" ActualExecutionMode = "Row" ActualElapsedms = "8591" ActualCPUms = "697" />
                          </RunTimeInformation>
                          <Filter StartupExpression = "false">
                            <RelOp AvgRowSize = "4855" EstimateCPU = "0.0030918" EstimateIO = "0.906088" EstimateRebinds = "0" EstimateRewinds = "0" EstimatedExecutionMode = "Row" EstimateRows = "2668" LogicalOp = "Clustered Index Scan" NodeId = "7" Parallel = "false" PhysicalOp = "Clustered Index Scan" EstimatedTotalSubtreeCost = "0.90918" TableCardinality = "2668">
                              <OutputList>
                                <ColumnReference Database = "[wiki]" Schema = "[dbo]" Table = "[pages_1]" Alias = "[p1]" Column = "id" />
                                <ColumnReference Database = "[wiki]" Schema = "[dbo]" Table = "[pages_1]" Alias = "[p1]" Column = "path" />
                                <ColumnReference Database = "[wiki]" Schema = "[dbo]" Table = "[pages_1]" Alias = "[p1]" Column = "body" />
                                <ColumnReference Database = "[wiki]" Schema = "[dbo]" Table = "[pages_1]" Alias = "[p1]" Column = "datetimecreated" />
                                <ColumnReference Database = "[wiki]" Schema = "[dbo]" Table = "[pages_1]" Alias = "[p1]" Column = "author" />
                                <ColumnReference Database = "[wiki]" Schema = "[dbo]" Table = "[pages_1]" Alias = "[p1]" Column = "version" />
                                <ColumnReference Database = "[wiki]" Schema = "[dbo]" Table = "[pages_1]" Alias = "[p1]" Column = "summary" />
                              </OutputList>
                              <RunTimeInformation>
                                <RunTimeCountersPerThread Thread = "0" ActualRows = "2668" ActualRowsRead = "2668" Batches = "0" ActualEndOfScans = "1" ActualExecutions = "1" ActualExecutionMode = "Row" ActualElapsedms = "653" ActualCPUms = "3" ActualScans = "1" ActualLogicalReads = "1247" ActualPhysicalReads = "0" ActualReadAheads = "0" ActualLobLogicalReads = "0" ActualLobPhysicalReads = "0" ActualLobReadAheads = "0" />
                              </RunTimeInformation>
                              <IndexScan Ordered = "false" ForcedIndex = "false" ForceScan = "false" NoExpandHint = "false" Storage = "RowStore">
                                <DefinedValues>
                                  <DefinedValue>
                                    <ColumnReference Database = "[wiki]" Schema = "[dbo]" Table = "[pages_1]" Alias = "[p1]" Column = "id" />
                                  </DefinedValue>
                                  <DefinedValue>
                                    <ColumnReference Database = "[wiki]" Schema = "[dbo]" Table = "[pages_1]" Alias = "[p1]" Column = "path" />
                                  </DefinedValue>
                                  <DefinedValue>
                                    <ColumnReference Database = "[wiki]" Schema = "[dbo]" Table = "[pages_1]" Alias = "[p1]" Column = "body" />
                                  </DefinedValue>
                                  <DefinedValue>
                                    <ColumnReference Database = "[wiki]" Schema = "[dbo]" Table = "[pages_1]" Alias = "[p1]" Column = "datetimecreated" />
                                  </DefinedValue>
                                  <DefinedValue>
                                    <ColumnReference Database = "[wiki]" Schema = "[dbo]" Table = "[pages_1]" Alias = "[p1]" Column = "author" />
                                  </DefinedValue>
                                  <DefinedValue>
                                    <ColumnReference Database = "[wiki]" Schema = "[dbo]" Table = "[pages_1]" Alias = "[p1]" Column = "version" />
                                  </DefinedValue>
                                  <DefinedValue>
                                    <ColumnReference Database = "[wiki]" Schema = "[dbo]" Table = "[pages_1]" Alias = "[p1]" Column = "summary" />
                                  </DefinedValue>
                                </DefinedValues>
                                <Object Database = "[wiki]" Schema = "[dbo]" Table = "[pages_1]" Index = "[PK_pages_1]" Alias = "[p1]" IndexKind = "Clustered" Storage = "RowStore" />
                              </IndexScan>
                            </RelOp>
                            <Predicate>
                              <ScalarOperator ScalarString = "[wiki].[dbo].[pages_1].[body] as [p1].[body] like N'%outlook%' OR [wiki].[dbo].[pages_1].[summary] as [p1].[summary] like N'%outlook%'">
                                <Logical Operation = "OR">
                                  <ScalarOperator>
                                    <Intrinsic FunctionName = "like">
                                      <ScalarOperator>
                                        <Identifier>
                                          <ColumnReference Database = "[wiki]" Schema = "[dbo]" Table = "[pages_1]" Alias = "[p1]" Column = "body" />
                                        </Identifier>
                                      </ScalarOperator>
                                      <ScalarOperator>
                                        <Const ConstValue = "N'%outlook%'" />
                                      </ScalarOperator>
                                    </Intrinsic>
                                  </ScalarOperator>
                                  <ScalarOperator>
                                    <Intrinsic FunctionName = "like">
                                      <ScalarOperator>
                                        <Identifier>
                                          <ColumnReference Database = "[wiki]" Schema = "[dbo]" Table = "[pages_1]" Alias = "[p1]" Column = "summary" />
                                        </Identifier>
                                      </ScalarOperator>
                                      <ScalarOperator>
                                        <Const ConstValue = "N'%outlook%'" />
                                      </ScalarOperator>
                                    </Intrinsic>
                                  </ScalarOperator>
                                </Logical>
                              </ScalarOperator>
                            </Predicate>
                          </Filter>
                        </RelOp>
                      </Sort>
                    </RelOp>
                  </Merge>
                </RelOp>
              </Top>
            </RelOp>
          </QueryPlan>
        </StmtSimple>
      </Statements>
    </Batch>
  </BatchSequence>
</ShowPlanXML>

Пожалуйста, используйте brentozar.com/pastetheplan, чтобы вставить свой план.

Dale K 05.08.2024 05:30

Независимо от окончательного решения, вам, вероятно, следует перейти от типов данных image, ntext и text, поскольку они устарели, по крайней мере, с SQL Server 2005 (перейдите на varbinary(max), nvarchar(max) и varchar(max) соответственно). Ссылка: ntext, text и image (Transact-SQL).

AlwaysLearning 05.08.2024 05:38

Хотя в некоторых ситуациях полнотекстовый поиск может быть полезен, он не всегда волшебным образом повышает производительность. См., например: Почему полнотекстовые запросы CONTAINS такие медленные.

AlwaysLearning 05.08.2024 05:40

Любой запрос фрагмента строки внутри более крупной строки, скорее всего, будет медленным.

Dale K 05.08.2024 07:28

Вы уверены, что опубликованный вами план выполнения предназначен для полнотекстового индекса? Потому что все, что я вижу, это сканы таблиц.

Dale K 05.08.2024 07:30

Содержит не может выполнять поиск по подстановочному знаку. Запросы такого типа всегда будут медленными, единственное решение — создать индекс, содержащий текстовые столбцы, чтобы ему, по крайней мере, не приходилось просматривать кластеризованный столбец, но это также может не помочь.

siggemannen 05.08.2024 11:50

Судя по вашему медленному результату, похоже, что путь тоже не индексируется. Возможно, разобьем ваш запрос на два: первый извлекает последнюю версию, а второй выполняет сопоставление текста.

siggemannen 05.08.2024 11:52

Представленный план выполнения запроса показывает, что 96% времени (стоимости) тратится на выборку строки с максимальной версией. Мне это кажется маловероятным. Однако попробуйте сделать выбор, используя row_number() (разделение по порядку пути по описанию версии) rn и rn=1. И предоставить актуальные данные об исполнении запроса

ValNik 05.08.2024 14:05

@AlwaysLearning понял, и да, я делаю это с этой БД, хотя на производительность это не влияет.

bdizz 05.08.2024 20:24

@siggemannen спасибо за идею. Я сделал первый запрос, который получает последнюю версию всех страниц, а затем второй, который запрашивает набор результатов из первого по поисковому запросу. Общее время моего тестирования сократилось примерно до 2 секунд (в 4 раза быстрее)!

bdizz 05.08.2024 20:25
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
10
54
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

В вашем запросе могут быть два улучшения.

  1. он выполняет подзапрос для каждой строки из-за вашего условия в подзапросе, поэтому вы можете запросить его с помощью INNER JOIN, получив таблицу, имеющую только максимальную версию.
  2. У вас есть несколько условий OR в основном предложенииwhere, которые могут неправильно использовать ваш индекс, даже если вы создали индекс полнотекстового поиска. Вы можете попробовать преобразовать запрос в UNIONS, чтобы решить эту проблему.

Ниже приведен измененный запрос, который вы можете использовать. Если вы не собираетесь использовать индекс, используйте Like вместо contains, так как это может быть накладным, но если вы используете индекс, вы можете использовать его, чтобы получить всю мощь индекса.

SELECT [id],[path],[body],[datetimecreated],[author],[version],[summary]
  FROM [dbo].[pages] p1
  INNER JOIN 
    (select     max(p2.[version]) as latest_version, p2.[path] as path
     from [dbo].[pages] p2
     group by p2.[path]
    ) X ON X.path = p1.path and X.latest_version = p1.version
where contains (body, '"outlook"')
order by   p1.[path] asc
UNION
SELECT [id],[path],[body],[datetimecreated],[author],[version],[summary]
  FROM [dbo].[pages] p1
  INNER JOIN 
    (select     max(p2.[version]) as latest_version, p2.[path] as path
     from [dbo].[pages] p2
     group by p2.[path]
    ) X ON X.path = p1.path and X.latest_version = p1.version
where CONTAINS(summary, '"outlook"')
order by   p1.[path] asc
UNION
SELECT [id],[path],[body],[datetimecreated],[author],[version],[summary]
  FROM [dbo].[pages] p1
  INNER JOIN 
    (select     max(p2.[version]) as latest_version, p2.[path] as path
     from [dbo].[pages] p2
     group by p2.[path]
    ) X ON X.path = p1.path and X.latest_version = p1.version
where CONTAINS (author, '"outlook"')
order by   p1.[path] asc

Попробовал ваш запрос, производительность не улучшилась, но спасибо за идею!

bdizz 05.08.2024 20:22
Ответ принят как подходящий

Сначала я преобразовал поле body в varchar(max) (что не дало никакого увеличения производительности), а затем разбил его на два запроса, первый из которых получает последнюю версию каждой страницы, а второй представляет собой запрос запросов, который ищет поисковая фраза. В результате получается в среднем 2 секунды на результат, что означает увеличение скорости в 4-5 раз. Спасибо!

Первый запрос:

select     [id], [path], [body], [datetimecreated], [author], [version], [summary]
from       pages p1
where     (version =
          (select     max(p2.version)
          from          pages p2
          where      p1.path = p2.path))
order by   p1.path asc

Второй запрос:

select id, path, datetimecreated, version
from    latest
where (body like '%outlook%'
      or summary like '%outlook%')
order by path asc

Другие вопросы по теме