Leonardo Pedroso Costa
MongoDB | SQL Server | Oracle

Como acompanhar o progresso da criação de um índice no MONGODB

Introdução

Como todos sabem, meu background técnico sempre foi forte em SQL Server e posteriormente em Oracle. 2 bancos de dados sensacionais que entregam robustez e valor para qualquer empresa que os adquirem, ao custo de algumas dezenas de milhares de dólares.

É fato que eu adoraria que o Failover Cluster do SQL Server tivesse os 2 nós ativos como o Oracle RAC usando ASM, é sensacional. Mas também gostaria de pagar somente a licença Enterprise Edition do Oracle e ter os recursos avançados de Compressão, Diagnostics Tuning, Particionamento, dentre outros. De fato não tem como fazer o omelete sem quebrar os ovos …

Agora estou em um desafio muito legal de aprender MongoDB : = ). Esse “banquinho” generoso ao custo de R$ 0.00 é calo no sapato de muito SGBD grande por aí. A licença Community é gratuita e eu sempre olhei com um certo receio para “esses bancos modinhas“, porém vi que o MongoDB além de não ser modinha, ele veio para ficar e tem mais tempo de vida do que eu tenho experiência com banco de dados.


Sem delongas .. vamos lá!

Como funciona no SQL Server?

No SQL Server, quando preciso ver o percentual de execução de alguma rotina (e não só a criação de um índice), eu simplesmente pesquiso a DMV sys.dm_exec_requests e olho a coluna percent_complete! Ela traz o percentual de execução e operações síncronas tais como:

ALTER INDEX REORGANIZE
AUTO_SHRINK option with ALTER DATABASE
BACKUP DATABASE
DBCC CHECKDB
DBCC CHECKFILEGROUP
DBCC CHECKTABLE
DBCC INDEXDEFRAG
DBCC SHRINKDATABASE
DBCC SHRINKFILE
RECOVERY
RESTORE DATABASE
ROLLBACK
TDE ENCRYPTION

A query em questão é a:

[code lang=”sql”]
SELECT command,
s.text,
start_time,
percent_complete,
CAST(((DATEDIFF(s,start_time,GetDate()))/3600) as varchar) + ‘ hour(s), ‘
+ CAST((DATEDIFF(s,start_time,GetDate())%3600)/60 as varchar) + ‘min, ‘
+ CAST((DATEDIFF(s,start_time,GetDate())%60) as varchar) + ‘ sec’ as running_time,
CAST((estimated_completion_time/3600000) as varchar) + ‘ hour(s), ‘
+ CAST((estimated_completion_time %3600000)/60000 as varchar) + ‘min, ‘
+ CAST((estimated_completion_time %60000)/1000 as varchar) + ‘ sec’ as est_time_to_go,
dateadd(second,estimated_completion_time/1000, getdate()) as est_completion_time
FROM sys.dm_exec_requests r
CROSS APPLY sys.dm_exec_sql_text(r.sql_handle) s
WHERE r.command in (‘ALTER INDEX REORGANIZE’,’RESTORE DATABASE’, ‘DBCC CHECKDB’, ‘BACKUP DATABASE’, ‘RESTORE LOG’, ‘RECOVERY’, ‘BACKUP LOG’)
[/code]

 

E pode ser executada diretamente no SQL Server Management Studio:

 

E no Oracle? Como faz?

No Oracle também temos algo similar, a view V$SESSION_LONGOPS (para instâncias standalone) ou GV$SESSION_LONGOPS (para instância em RAC) permite consultar operações que demore mais que 6 segundos no servidor. As informações mais comuns que já peguei nessa View foram:

BACKUP
RESTORE
EXPDP
IMPDP
STATISTICS GATHERING
QUERY EXECUTION

E a query que utilizo para acompanhar a execução de rotinas no Oracle é essa abaixo:

[code lang=”sql”]
SELECT inst_id,sid, serial#, opname, username,TO_CHAR(start_time,’DD/MM/YYYY HH24:MI:SS’),TO_CHAR(last_update_time,’DD/MM/YYYY HH24:MI:SS’),
round(time_remaining/60,2) "REMAIN MINS", round(elapsed_seconds/60,2) "ELAPSED MINS", round((time_remaining+elapsed_seconds)/60,2) "TOTAL MINS",
ROUND(SOFAR/TOTALWORK*100,2) "%_COMPLETE", message
FROM gv$session_longops
WHERE TOTALWORK != 0 AND sofar <> totalwork AND time_remaining > 0;
[/code]

E pode ser executada tanto no SQLPLUS, como no SQL Developer e afins:

 

E por fim, no MONGO

Alguns minutos no google e stackoverflow e descobri o seguinte comando: db.currentOp(true). Esse comando basicamente traz TUDO que tiver sendo executado na instância. Para trazer as informações de percentual de execução no mongo, basta rodar o comando abaixo na console:

[code lang=”sql”]
db.currentOp(true).inprog.forEach(function(op){ if(op.msg!==undefined) print(op.msg) })
[/code]

O resultado esperado é esse abaixo:

rsGalo2013:PRIMARY> db.currentOp(true).inprog.forEach(function(op){ if(op.msg!==undefined) print(op.msg) })
Index Build (background) Index Build (background): 14637939/25352240 57%

rsGalo2013:PRIMARY> db.currentOp(true).inprog.forEach(function(op){ if(op.msg!==undefined) print(op.msg) })
Index Build (background) Index Build (background): 15626259/25352267 61%

rsGalo2013:PRIMARY> db.currentOp(true).inprog.forEach(function(op){ if(op.msg!==undefined) print(op.msg) })
Index Build (background) Index Build (background): 19802186/25352348 78%

rsGalo2013:PRIMARY> db.currentOp(true).inprog.forEach(function(op){ if(op.msg!==undefined) print(op.msg) })
Index Build (background) Index Build (background): 19802186/25352348 87%

rsGalo2013:PRIMARY> db.currentOp(true).inprog.forEach(function(op){ if(op.msg!==undefined) print(op.msg) })
Index Build (background) Index Build (background): 19802186/25352348 99%

Outra maneira de checar em tempo real é através do arquivo de log mongod.log. Basta entrar na pasta de logs do servidor conforme script abaixo e rodar um TAIL -F no arquivo, filtrando por “INDEX BUILD”:

[code lang=”sql”]
root@galo2013 [/var/log/mongodb] # tail -f mongod.log | grep "Index Build"
[/code]

O resultado esperado é esse abaixo:

2021-03-20T13:24:40.016-0300 I – [conn13809246] Index Build (background): 12426100/25378872 1%
2021-03-20T13:24:43.002-0300 I – [conn13809246] Index Build (background): 12442900/25378872 2%
2021-03-20T13:24:46.015-0300 I – [conn13809246] Index Build (background): 12463700/25378872 3%
2021-03-20T13:24:49.010-0300 I – [conn13809246] Index Build (background): 12480900/25378872 4%
2021-03-20T13:24:52.012-0300 I – [conn13809246] Index Build (background): 12502000/25378872 5%
2021-03-20T13:24:55.009-0300 I – [conn13809246] Index Build (background): 12527800/25378872 6%
2021-03-20T13:24:58.004-0300 I – [conn13809246] Index Build (background): 12556600/25378872 7%
2021-03-20T13:25:01.018-0300 I – [conn13809246] Index Build (background): 12576200/25378872 8%
2021-03-20T13:25:01.018-0300 I – [conn13809246] Index Build (background): 12576200/25378872 99%

Bem pessoal, por hoje é isso! Espero que essa informação seja de grande utilidade pra vocês, pois pra mim foi extremamente útil.

Ah, escrevi esse post com informações retiradas das fontes abaixo 😀 Vale a pena a pesquisa.

Fonte:
https://docs.mongodb.com/manual/reference/method/db.currentOp/
https://stackoverflow.com/questions/22309268/mongodb-status-of-index-creation-job
https://docs.microsoft.com/pt-br/sql/relational-databases/system-dynamic-management-views/sys-dm-exec-requests-transact-sql?view=sql-server-ver15

Leonardo Pedroso

Leonardo Pedroso

Profissional de TI experiência em administração de banco de dados: SQL Server 2000 a 2019, Oracle 11g a 19c, PostgreSQL, MySQL, MongoDB, Cassandra. Atua realizando análise de desempenho, DR e HA, implantação, administração de banco de dados em cluster e implementação de projetos de banco de dados NoSQL (MongoDB, Cassandra), bem como automação de processos utilizando Shell script, Powershell (dbatools), e players de Cloud: Azure e Aws.