Оптимизация запросов в базе данных SQL Server с таблицами, содержащими более 30 миллионов строк.

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

Это структура таблицы.

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

Только для COUNT строк таблицы это занимает более 3 минут. Есть ли какой-либо инструмент или запрос для оптимизации таблицы и ускорения выполнения запросов?

PS: я работаю над четырехъядерным процессором, 8 ГБ ОЗУ, виртуальная машина Windows 7

ИЗМЕНИТЬ

Это скрипт, который генерирует таблицу:

SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE TABLE [dbo].[L_Customer]
(
    [LC_Id] [int] IDENTITY(1,1) NOT NULL,
    [A] [nvarchar](max) NULL,
    [B] [nvarchar](max) NULL,
    [C] [nvarchar](max) NULL,
    [D] [nvarchar](max) NULL,
    [E] [nvarchar](max) NULL,
    [F] [nvarchar](max) NULL,
    [G] [nvarchar](max) NULL,
    [H] [float] NULL,
    [I] [float] NULL,
    [L] [nvarchar](max) NULL,
    [M] [nvarchar](max) NULL,
    [N] [nvarchar](max) NULL,
    [O] [nvarchar](max) NULL,
    [P] [nvarchar](max) NULL,
    [Q] [nvarchar](max) NULL,
    [W] [int] NULL,

    CONSTRAINT [PK_L_Customer] 
       PRIMARY KEY CLUSTERED ([LC_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]
GO

(Это не настоящие имена столбцов)

Запрос простой:

SELECT COUNT(LC_Id) 
FROM dbo.L_Customer

Это заняло 3 минуты и 10 секунд, и это план выполнения:

<?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.1" Build="10.50.1600.1" xmlns="http://schemas.microsoft.com/sqlserver/2004/07/showplan">
  <BatchSequence>
    <Batch>
      <Statements>
        <StmtSimple StatementCompId="1" StatementEstRows="1" StatementId="1" StatementOptmLevel="FULL" StatementSubTreeCost="806.254" StatementText="select count(LC_Id) from Anagrafiche_2.dbo.L_Customer&#xD;&#xA;" StatementType="SELECT" QueryHash="0x859AA6DAAAAF58AD" QueryPlanHash="0xBF9F762C316AEE73">
          <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="0" CachedPlanSize="16" CompileTime="1" CompileCPU="1" CompileMemory="160">
            <RelOp AvgRowSize="11" EstimateCPU="18.1674" EstimateIO="0" EstimateRebinds="0" EstimateRewinds="0" EstimateRows="1" LogicalOp="Compute Scalar" NodeId="0" Parallel="false" PhysicalOp="Compute Scalar" EstimatedTotalSubtreeCost="806.254">
              <OutputList>
                <ColumnReference Column="Expr1003" />
              </OutputList>
              <ComputeScalar>
                <DefinedValues>
                  <DefinedValue>
                    <ColumnReference Column="Expr1003" />
                    <ScalarOperator ScalarString="CONVERT_IMPLICIT(int,[Expr1006],0)">
                      <Convert DataType="int" Style="0" Implicit="true">
                        <ScalarOperator>
                          <Identifier>
                            <ColumnReference Column="Expr1006" />
                          </Identifier>
                        </ScalarOperator>
                      </Convert>
                    </ScalarOperator>
                  </DefinedValue>
                </DefinedValues>
                <RelOp AvgRowSize="11" EstimateCPU="18.1674" EstimateIO="0" EstimateRebinds="0" EstimateRewinds="0" EstimateRows="1" LogicalOp="Aggregate" NodeId="1" Parallel="false" PhysicalOp="Stream Aggregate" EstimatedTotalSubtreeCost="806.254">
                  <OutputList>
                    <ColumnReference Column="Expr1006" />
                  </OutputList>
                  <RunTimeInformation>
                    <RunTimeCountersPerThread Thread="0" ActualRows="1" ActualEndOfScans="1" ActualExecutions="1" />
                  </RunTimeInformation>
                  <StreamAggregate>
                    <DefinedValues>
                      <DefinedValue>
                        <ColumnReference Column="Expr1006" />
                        <ScalarOperator ScalarString="Count(*)">
                          <Aggregate AggType="countstar" Distinct="false" />
                        </ScalarOperator>
                      </DefinedValue>
                    </DefinedValues>
                    <RelOp AvgRowSize="9" EstimateCPU="33.307" EstimateIO="754.779" EstimateRebinds="0" EstimateRewinds="0" EstimateRows="30279000" LogicalOp="Clustered Index Scan" NodeId="2" Parallel="false" PhysicalOp="Clustered Index Scan" EstimatedTotalSubtreeCost="788.086" TableCardinality="30279000">
                      <OutputList />
                      <RunTimeInformation>
                        <RunTimeCountersPerThread Thread="0" ActualRows="30278956" ActualEndOfScans="1" ActualExecutions="1" />
                      </RunTimeInformation>
                      <IndexScan Ordered="false" ForcedIndex="false" NoExpandHint="false">
                        <DefinedValues />
                        <Object Database="[Anagrafiche_2]" Schema="[dbo]" Table="[L_Customer]" Index="[PK_L_Customer]" IndexKind="Clustered" />
                      </IndexScan>
                    </RelOp>
                  </StreamAggregate>
                </RelOp>
              </ComputeScalar>
            </RelOp>
          </QueryPlan>
        </StmtSimple>
      </Statements>
    </Batch>
  </BatchSequence>
</ShowPlanXML>

person LS_    schedule 21.10.2016    source источник
comment
Таким образом, запрос представляет собой простой SELECT COUNT(*) FROM your_table, ни больше, ни меньше? Кроме того, у вас есть КЛАСТЕРНЫЙ ИНДЕКС, определенный для этой таблицы?   -  person TT.    schedule 21.10.2016
comment
meta.stackoverflow.com/questions/285551/   -  person a_horse_with_no_name    schedule 21.10.2016
comment
@ТТ. еще проще, я просто COUNT LC_Id (Primary key), который является Integer, и это занимает до 3 минут. Я не определил его, но, насколько мне известно, Sql Server по умолчанию создает кластеризованный индекс для столбца (столбцов) первичного ключа (правильно ли это?)   -  person LS_    schedule 21.10.2016
comment
Пожалуйста, включите в свой ответ фактический запрос, план выполнения и определение таблицы (включая индексы, кластеризованные или иные). Как уже указал наш постоянный безымянный конь, не размещайте код на скриншотах.   -  person TT.    schedule 21.10.2016
comment
Если вы не установили индексы часто запрашиваемых столбцов, вы можете попробовать. Вы оцените его помощь при запросе объемных данных.   -  person zbads    schedule 21.10.2016
comment
@GordonLinoff Из документов говорится, что он автоматически создается на PRIMARY KEY если кластеризованный индекс для таблицы еще не существует и вы не указали уникальный некластеризованный индекс   -  person LS_    schedule 21.10.2016
comment
Сколько времени нужно для запуска SELECT COUNT(*) FROM dbo.L_Customer?   -  person TT.    schedule 21.10.2016
comment
@ТТ. Столько же времени ушло на его запуск. У меня есть план выполнения запроса, как я могу им поделиться? (он сохраняется как XML)   -  person LS_    schedule 21.10.2016
comment
Я бы добавил его как блок кода.   -  person TT.    schedule 21.10.2016
comment
@ТТ. Ok! Я добавил план выполнения запроса   -  person LS_    schedule 21.10.2016
comment
Пожалуйста, обратитесь к следующим вопросам на StackOverflow с подходящими ответами: 1 и 2. SELECT COUNT(...) ... сканирует индекс, чтобы подсчитать все строки. Ответы на вопросы показывают, как обойти это сканирование.   -  person TT.    schedule 21.10.2016
comment
Вот один из dba.stackexchange   -  person TT.    schedule 21.10.2016
comment
@сигно . . . Спасибо тебе за пояснение. Я удалил комментарий. Мотивом комментария было то, что кластеризованный индекс не обязательно должен быть первичным ключом, но я явно неправильно сформулировал это.   -  person Gordon Linoff    schedule 22.10.2016