---
title: "Índice de Documents (relatórios de documentos)"
description: "Como o Signer cria o índice da tabela Documents usado pelos relatórios de documentos ao atualizar para a 3.0.0, e o que fazer se o processo automático falhar."
canonical: "https://docs.lacunasoftware.com/articles/signer/on-premises/update-30-documents-index"
locale: "pt-BR"
product: "Signer"
last_updated: "2026-10-16"
---

# Índice de Documents (relatórios de documentos)

Esta página explica o índice `IX_Documents_SubscriptionId_CreationDateUtc`, criado na atualização para a versão **3.0.0** (SIG-1919), e o que fazer se a criação automática falhar. Ele se aplica a **todas** as instâncias que atualizam de uma versão anterior à 3.0.0.

> **Observação**
>
> É fortemente recomendado fazer a atualização em um horário de pouco uso. Enquanto o índice não existe, a aplicação funciona normalmente. O custo é que os relatórios de documentos podem ficar lentos ou estourar o tempo limite em organizações com muitos documentos.

## O que esse índice melhora

Os relatórios de documentos da organização, do usuário e da pasta carregam todos os documentos de um período, filtrando pela assinatura (`SubscriptionId`) e ordenando pela data de criação (`CreationDateUtc`). Sem um índice com essas duas colunas, o banco de dados precisa ordenar um volume grande de documentos antes de devolver as linhas, o que causava timeout na geração do relatório mensal de organizações grandes.

```text
IX_Documents_SubscriptionId_CreationDateUtc
  chaves: SubscriptionId (crescente), CreationDateUtc (crescente)
```

Se um relatório estourar o tempo limite, o log da aplicação registra um aviso sugerindo aumentar `ReportDatabaseCommandTimeoutSeconds` ou verificar se o índice existe.

## Como o processo automático funciona

1. **Migração (`AddDocumentsReportIndex`).** Executada na primeira inicialização. Ela **não cria** o índice, para não bloquear a tabela `Documents` durante a atualização.
2. **Enfileiramento na inicialização.** O `DocumentsReportIndexBuilderStarter` verifica se o índice existe. Se não existir (ou se não conseguir verificar), enfileira no Hangfire o `CreateDocumentsReportIndexJob` (fila *Low*, até 3 tentativas, sem execução concorrente). Isso se repete a cada inicialização enquanto o índice não existir.
3. **Job `CreateDocumentsReportIndexJob`.** Se o índice já existe, não faz nada. Caso contrário, identifica a edição do SQL Server e cria o índice com `SORT_IN_TEMPDB = ON` e timeout de `DocumentsReportIndexCommandTimeoutSeconds` (padrão `7200`):
   * **ONLINE** (não bloqueia a tabela) no Azure SQL Database, SQL Managed Instance e SQL Server Enterprise ou Developer.
   * **OFFLINE** nas demais edições, o que **bloqueia a tabela `Documents`** até terminar. O job registra um aviso no log.
   * Se a criação *ONLINE* falhar por um erro que não seja timeout, o job tenta criar *OFFLINE*. Se a criação *ONLINE* estourar o **timeout**, ela **não** é repetida *OFFLINE*, para não bloquear a tabela por ainda mais tempo.

### Como acompanhar

* No painel do Hangfire (`/hangfire`), acompanhe o `CreateDocumentsReportIndexJob`.
* Nos logs da aplicação, procure por `Creating IX_Documents_SubscriptionId_CreationDateUtc`, `created successfully` ou `Failed to create`.
* No banco de dados:

```sql
SELECT name, is_disabled FROM sys.indexes
WHERE name = 'IX_Documents_SubscriptionId_CreationDateUtc' AND object_id = OBJECT_ID('Documents');
```

## O que fazer se o processo automático falhar

O job falhou se ele esgotou as 3 tentativas no Hangfire, ou se os logs mostram timeout ou deadlock (erro SQL 1205) e a consulta acima não retorna o índice.

### 1. Aumentar o timeout e reiniciar

Aumente `DocumentsReportIndexCommandTimeoutSeconds` (veja [Configurações *General*](https://docs.lacunasoftware.com/articles/signer/on-premises/settings#configurações-general)) e reinicie a aplicação. O job é enfileirado novamente na inicialização.

### 2. Criar o índice manualmente

Se ainda estourar o tempo limite, crie o índice no banco de dados. Faça isso em uma janela de baixo tráfego e em **uma única sessão**: duas criações *ONLINE* simultâneas na mesma tabela entram em deadlock na troca final de locks, e o `IF NOT EXISTS` não protege contra execução concorrente. Em edições sem suporte a *ONLINE* (SQL Server Standard e Express), use `ONLINE = OFF`, que **bloqueia a tabela** durante a criação.

```sql
IF NOT EXISTS (SELECT 1 FROM sys.indexes WHERE name = 'IX_Documents_SubscriptionId_CreationDateUtc' AND object_id = OBJECT_ID('Documents'))
CREATE INDEX [IX_Documents_SubscriptionId_CreationDateUtc] ON [Documents] ([SubscriptionId] ASC, [CreationDateUtc] ASC)
WITH (ONLINE = ON, SORT_IN_TEMPDB = ON);
```

Cuidados:

* **Deadlock.** O build *ONLINE* disputa locks com as escritas da aplicação e pode causar deadlock (erro 1205); a vítima pode ser uma transação da aplicação em vez do build. Depois da criação, verifique nos logs da aplicação se houve erros 1205 no período.
* **Azure SQL Database.** A criação de índice é sempre registrada integralmente no log de transações, então o tempo depende do limite de log do nível de serviço. Níveis baixos sofrem throttle (espera `LOG_RATE_GOVERNOR`; a espera `CXCONSUMER` é benigna). Se puder, escale o nível de serviço **antes** de iniciar o build, pois trocar o nível no meio derruba a criação em andamento.
* **Criação retomável (opcional).** No SQL Server 2019 ou superior e no Azure SQL, adicione `RESUMABLE = ON` ao `WITH` para que uma interrupção não descarte o progresso (consulte `sys.index_resumable_operations` e use `ALTER INDEX ... RESUME` ou `ABORT`). `RESUMABLE = ON` não pode ser combinado com `SORT_IN_TEMPDB = ON`; remova essa opção.

### 3. Confirmar

Execute a consulta da seção [Como acompanhar](https://docs.lacunasoftware.com/articles/signer/on-premises/update-30-documents-index#como-acompanhar): o índice deve estar presente e `is_disabled = 0`. Com o índice criado, o job termina sem refazer a criação na próxima inicialização.
