#Globais

0 Seguidores · 26 Postagens

Globais são arrays esparsos multidimensionais que são armazenados na Plataforma de Dados InterSystems. Tudo nos produtos InterSystems é armazenado em Globais: Classes, Tabelas, Documentos, Código.

Documentação.

Artigo Heloisa Paiva · Out. 30, 2025 4m read

Ao usar SQL padrão ou a camada de objetos no InterSystems IRIS, a consistência dos metadados é geralmente mantida por meio de validação integrada e imposição de tipo. No entanto, sistemas legados que ignoram essas camadas—acessando globals diretamente—podem introduzir inconsistências sutis e graves.

1
0 13
Artigo Heloisa Paiva · Set. 16, 2025 3m read

Começar a usar ObjectScript é realmente empolgante, mas também pode parecer um pouco estranho se você está acostumado com outras linguagens. Muitos iniciantes tropeçam nos mesmos obstáculos, então aqui estão alguns "pegadinhas" que você vai querer evitar. (Além de algumas dicas amigáveis para contorná-las.)

Nomear Coisas Aleatoriamente

Todos nós já fomos culpados de nomear algo como Test1 ou MyClass apenas para seguir em frente rapidamente. Mas quando seu projeto cresce, esses nomes se tornam um pesadelo.

0
0 35
Artigo Heloisa Paiva · Ago. 25, 2025 3m read

Ao começar a usar o InterSystems IRIS ou Cache, os desenvolvedores frequentemente se deparam com três conceitos principais: Objetos Dinâmicos, Globals e Tabela Relacional. Cada um tem seu papel na construção de soluções escaláveis e fáceis de manter. Neste artigo, vamos percorrer exemplos de código práticos, destacar as melhores práticas e mostrar como esses conceitos se conectam.

1. Trabalhando com Objetos Dinâmicos

0
0 30
Artigo Heloisa Paiva · Ago. 9, 2025 3m read

A ObjectScript pode parecer apenas mais uma linguagem de programação, mas aqui está a reviravolta:

Seu código pode viver para sempre (sim, mesmo depois que você tiver passado para outro projeto). É por isso que é importante mantê-lo organizado, fácil de ler e seguro contra bugs misteriosos.

(Um guia para iniciantes para manter seu código limpo, amigável e à prova de futuro)

Bem-vindo à selva do ObjectScript, onde seu código pode ter escopo global e natureza persistente. Vamos manter as coisas limpas, legíveis e resistentes a bugs.

 1️⃣Nomeie como se fosse sério

0
0 27
Pergunta Graciano dos Santos Duarte · Jun. 2, 2025

Prezado senhores,

Estou tentando consultar os dados das tabelas de um banco de dados caché. Ele possui dados nas globais.  Também possui tabelas SQL sem registros, mas com a estrutura das classes do banco de dados. Quando vou consultar os dados através do driver ODBC não retorna nenhum dado. Mesmo pelo painel administrativo as consultas SQL não retornam dados. Sabem me dizer o que pode estar acontecendo?

At.te

Graciano dos Santos Duarte

5
0 61
Artigo Heloisa Paiva · Maio 26, 2025 8m read

Introdução

Olá! Neste artigo, discutirei a degradação de banco de dados, um tipo de problema de integridade de dados que se pode enfrentar ao usar o IRIS. Primeiro, farei uma revisão da estrutura dos bancos de dados IRIS. Em seguida, discutirei como a degradação de banco de dados pode se manifestar e as causas comuns de problemas de degradação. Concluirei com dicas gerais que damos aos nossos clientes sobre como prevenir ou se preparar para problemas de degradação de banco de dados.

Estrutura do Banco de Dados IRIS

O que exatamente é um banco de dados? Um banco de dados IRIS é um único arquivo que consiste em uma unidade fundamental chamada "bloco". Ele contém vários blocos de tamanhos iguais (normalmente 8kb) em ordem sequencial. Todos esses blocos "apontam" uns para os outros armazenando o offset no banco de dados onde reside o bloco para o qual apontam. Essa rede de blocos forma uma configuração que se assemelha a uma "floresta" do que são chamadas de árvores balanceadas, ou B-trees. Cada global é representada por uma B-tree separada, e cada B-tree é acessível por meio de um Bloco de Diretório Global de nível superior que contém ponteiros para todas as B-trees globais no banco de dados.

A característica que define uma B-tree é que todos os blocos de dados de "folha" estão no mesmo nível. Isso significa que, sempre que um bloco de ponteiro superior é preenchido, outra camada de ponteiro é adicionada acima dele, permitindo que a B-tree escale teoricamente de forma indefinida. No início de cada bloco, há uma quantidade de bytes que indicam alguns metadados sobre aquele bloco e os blocos ao seu redor. Por exemplo, cada bloco contém informações sobre seu número de bloco, a quantidade de bytes de dados no bloco, o tipo de bloco (ponteiro ou dados), a ordenação, etc. O bloco também contém informações sobre blocos relacionados, como o número do bloco à sua direita, o primeiro nó do bloco à sua direita e as diferenças de byte entre o último nó do bloco e o bloco à direita.

Aqui está uma representação de como se parece uma B-tree global. As linhas verdes representam ponteiros entre diferentes níveis de blocos, e as linhas laranja representam ponteiros entre os blocos e seus blocos vizinhos à direita. Um valor de bloco à direita de 0 é usado quando o bloco está na borda direita da árvore.

image

Degradação do Banco de Dados

Problemas de integridade do banco de dados ocorrem quando a estrutura interna de um banco de dados apresenta alguma inconsistência lógica, ou quando o banco de dados não corresponde ao formato que o IRIS espera. Isso pode acontecer de várias maneiras:

  • Integridade Referencial: Os ponteiros entre blocos de ponteiros e blocos de dados, ou os ponteiros de direção "direita" entre blocos de dados, estão inconsistentes. Por exemplo, um bloco de ponteiros pode indicar que o primeiro nó de um bloco de dados para o qual ele aponta é ^x(10), enquanto o primeiro nó desse bloco de dados é, na verdade, ^x(20).
  • **Integridade dos Dados: ** Os dados dos blocos de ponteiros ou dos blocos de dados estão corrompidos. Por exemplo, os primeiros bytes de cada bloco contêm metadados sobre o próprio bloco e seus blocos relacionados, começando no offset 0. Se estes estiverem localizados em outro offset, isso resultaria na corrupção do bloco.
  • Integridade da Aplicação: Isso ocorre quando o banco de dados está no formato esperado pelo IRIS, mas há alguma inconsistência lógica relacionada a como a aplicação deveria funcionar. Por exemplo, digamos que esperamos que todos os dados do médico sejam salvos no global ^Hospital.DoctorsD, e os índices desses médicos sejam salvos no ^Hospital.DoctorsI. Se um médico tivesse seus dados no global de dados, mas não tivesse um índice correspondente no global de índices, isso seria uma forma de problema de integridade da aplicação.

Causas Comuns de Degradação

Aqui, abordarei algumas das causas comuns de degradação do banco de dados que observamos em nossos clientes.

Cache de Escrita do Windows

O cache de escrita do Windows é um recurso do Windows que pode levar a problemas de degradação do banco de dados. A ideia por trás dessa configuração é que o Windows armazenará em buffer as escritas em disco na memória e as gravará no disco em pacotes maiores. Isso ajuda a melhorar o desempenho em certos casos, pois as escritas em disco são lentas, e fazê-las em pacotes maiores permite uma escrita mais eficiente. Por exemplo, imagine que seu disco esteja dividido em blocos de 1024 bytes, e você tenha um aplicativo tentando escrever 256 blocos de dados de 4 bytes. Em vez de fazer 256 escritas separadas no disco, o que seria bastante lento, o cache de escrita economiza tempo armazenando essas escritas na memória e gravando-as com muito menos frequência.

No entanto, isso pode criar problemas quando há perda de energia. Se o sistema operacional estiver armazenando dados na memória que normalmente já teriam sido gravados no disco, uma perda de energia pode fazer com que esses dados sejam perdidos e irrecuperáveis, já que a memória RAM é volátil. Por essa razão, frequentemente recomendamos que nossos clientes desativem o cache de escrita do Windows quando não for necessário.

Cache de Escrita de Hardware

Assim como os sistemas operacionais usarão a RAM para armazenar em cache as gravações em disco, algumas unidades de disco de nível empresarial também armazenarão em cache as gravações em disco para fins de eficiência. Certos SSDs, por exemplo, contêm um buffer DRAM que pode armazenar gravações para escrevê-las em grandes pacotes para aumentar o desempenho. Infelizmente, assim como no cache de escrita em nível de sistema operacional, a DRAM e a memória de hardware em geral são voláteis e não serão preservadas em caso de perda de energia. Isso pode ser mitigado garantindo que a unidade de disco seja alimentada por baterias ou alguma outra forma de Sistema de Alimentação Ininterrupta (UPS) para que possa descarregar o buffer de memória em caso de falha de energia.

VMware

VMware é uma solução de hospedagem em nuvem que muitos de nossos clientes usam para executar nossos produtos. Houve uma série de problemas conhecidos com o VMware que podem levar a problemas de integridade de dados. Estes são detalhados nos seguintes avisos:

  • Aviso: VMWare vSAN e Integridade de Dados (link) : Há um problema conhecido relacionado a operações de extensão de disco com VMs executando VMware vSAN, uma solução de armazenamento oferecida pela VMware.
  • Aviso: VMWare vSphere e Integridade de Dados (link) : O SEsparse, um formato de snapshot para máquinas VMware, possui um problema conhecido de integridade de dados.
  • Aviso: Erros de Consistência de Dados do VMware vSAN (link) : Existem certas instruções x86 no conjunto de instruções AVX-512 que podem levar a problemas de integridade de dados quando usadas com o vSAN.

Aconselhamento Geral

Aqui estão algumas recomendações gerais que fornecemos aos nossos clientes ao ajudá-los a se recuperar de problemas de degradação do banco de dados.

Backups

Ao lidar com problemas de degradação do banco de dados, nosso primeiro recurso, surpreendentemente, não é tentar reparar. Reparar bancos de dados manualmente pode ser um processo complicado e nem sempre produtivo, devido à grande escala e complexidade dos problemas típicos de degradação. Em vez disso, inicialmente tentaremos recuperar de um backup para restaurar o banco de dados a um estado saudável. Por essa razão, pedimos aos nossos clientes que façam backups frequentes.

Os backups também são extremamente úteis para realizar uma Análise da Causa Raiz (ACR) sobre o porquê da degradação ter ocorrido em primeiro lugar. Com um backup, podemos ver como era o estado saudável para comparação com o estado não saudável. Também podemos ver como a degradação mudou ou se espalhou ao longo do tempo para rastrear sua origem.

Guia para fazer backups: link

Verificações de Integridade

É vital para a ACR que detectemos a degradação do banco de dados o mais rápido possível. Isso é importante porque, muitas vezes, a degradação acontece devido a algum aspecto do estado do sistema, seja no nível da aplicação, do sistema operacional ou do hardware.

Por essa razão, pedimos aos nossos clientes que executem verificações frequentes da rotina ^Integrity. Essa rotina verifica bancos de dados e globais para garantir que eles tenham o formato esperado pelo IRIS. Se você encontrar degradação em seus bancos de dados, pode entrar em contato imediatamente com o WRC (Worldwide Response Center) e nós o auxiliaremos no reparo e, em seguida, na realização de uma Análise da Causa Raiz (ACR) para encontrar a origem do problema.

Guia para executar verificações de integridade: link

Também é importante executar verificações de integridade fora do IRIS no sistema operacional e no hardware em que a instância do IRIS está sendo executada, pois o IRIS funciona de forma intrínseca com o sistema operacional e o hardware para gerenciar os dados corretamente. Isso pode ser feito por meio de utilitários do sistema operacional, como fsck (UNIX) e chkdsk (Windows).

Conclusão

No mundo dos dispositivos de armazenamento modernos e sistemas operacionais avançados, os problemas de integridade de dados não são tão frequentes quanto antes. No entanto, eles ainda ocorrem e podem levar a problemas sérios com a disponibilidade da aplicação e perda de dados quando acontecem. Para isso, pedimos aos nossos clientes que verifiquem frequentemente a integridade de seus dados e sistemas, e nos contatem sempre que identificarem um problema, para que possamos ajudar a restaurar seus sistemas o mais rápido possível. Obrigado!

0
0 30
Artigo Heloisa Paiva · Ago. 16, 2024 3m read

Rubrica InterSystems FAQ 

Globais temporárias armazenadas nas bases de dados IRISTEMP/CACHETEMP são usadas quando um processo não precisa guardar dados indefinidamente, mas requere a poderosa performance das globais. As bases de dados IRISTEMP/CACHETEMP não são jounralizadas, então usar globais temporárias não cria arquivos de journal.

O sistema usa as bases de dados IRISTEMP/CACHETEMP para armazenamento temporário e estão disponíveis para usuários para o mesmo objetivo.

0
0 60
Artigo Danusa Calixto · Nov. 28, 2023 8m read

Visão geral

A documentação online contém o tópico Defining and Using Class Queries (Definir e usar consultas de classe) para referência-

A personalização direta de procedimentos armazenados com ObjectScript tem sido útil para acessar o armazenamento NoSQL e as mensagens externas pela integração, para apresentar a saída em um formato tabular.

Por exemplo: um aplicativo que já usa 90% da interação SQL de um front-end também pode estender esse acesso aos outros 10% da funcionalidade de plataforma necessária, pelo mesmo acesso SQL.

A finalidade deste artigo é explorar como alcançar o mesmo efeito usando os métodos do Embedded Python.

Figura 1: procedimento armazenado como um SQL gateway para outra funcionalidade de plataforma

Demonstração

Para esse exemplo, foi definido o seguinte armazenamento NoSQL:

^alwo.IndexBook("A",1)="abc"
^alwo.IndexBook("A",2)="def"
^alwo.IndexBook("B")=""
^alwo.IndexBook("C")=""
^alwo.IndexBook("D",1)="gef"
^alwo.IndexBook("E",1)="ijk"
^alwo.IndexBook("E",2)="lmn"

Para teste, o procedimento armazenado pode ser executado em um terminal:

GBI>Do $SYSTEM.SQL.Shell()
SQL Command Line Shell
----------------------------------------------------
 
The command prefix is currently set to: <<nothing>>.
Enter <command>, 'q' to quit, '?' for help.

[SQL]GBI>>call alwo.PyProcTest_GetNotes('A')

Dumping result #1
Tab     NoteId  NoteText
A       1       abc
A       2       def
B       0
C       0
D       0
E       0
 
6 Rows(s) Affected
statement prepare time(s)/globals/cmds/disk: 0.0003s/4/100/0ms
          execute time(s)/globals/cmds/disk: 0.0009s/12/1,096/0ms
                                query class: %sqlcq.GBI.cls27, %Library.ProcedureContext
---------------------------------------------------------------------------

Como foi fornecida a aba ( primeira chave ) "A", os dados dos sub-nós são expandidos e retornados como registros.

Os outros nós que não foram selecionados ou não contêm dados são retornados como registros "0".

Conceitos de código

Quando uma consulta ( GetNotes ) é implementada em uma classe, o conteúdo da consulta pode ser obtido apenas com SQL.

Após a compilação, são gerados três class methods:

  • GetNotesExecute
  • GetNotesFetch
  • GetNotesClose

Há vários cenários em que os dados não são SQL:

  • Globais NoSQL
  • Interação parametrizada com um sistema externo para recuperar e consolidar dados

Ao implementar esses três métodos diretamente, é possível controlar o acesso e dar respostas tabulares para uma ampla variedade de recursos de plataforma.

Estas são algumas das variações de interação:

Armazenar em cache todos os dados de resposta antecipadamente

1. O método GetNotesExecute acessaria os recursos para criar uma reposta em um global temporário.

Isso seria útil para uma visão consistente sobre os dados, o que pode envolver o bloqueio do acesso a atualizações por um breve período.

2. O método GetNotesFetch seria chamado repetidamente, retornando registros dos dados temporários

3. The GetNotesClose limparia e excluiria os dados temporários

Dados de respostas dinâmicas

1. O método GetNotesExecute é chamado. Isso não faz muito coisa além de iniciar um contexto qHandle disponível para o método Fetch

2. O método GetNotesFetch é chamado. Sempre que um novo registro é recuperado dinamicamente

3. O método GetNotesClose exige pouca ou nenhuma limpeza

Essa é a abordagem usada no código de exemplo.

Oportunidades de paginação etc.

Dependendo do cenário, o preenchimento dinâmico de lotes de registros de retorno pode ser usado para reduzir a necessidade de executar uma "consulta completa" quando só é necessária uma área da fatia de registros de retorno.

O código

O método execute tem uma expressão $C(0). Isso serve apenas para corresponder a uma string Null, que é diferente de uma string vazia.

Uma string nula pode ser passada quando um procedimento armazenado é invocado com um argumento de string vazio.

O método GetNotesFetch atua como um wrapper objectscript para GetNotesFetchPy, onde ocorre o trabalho de verdade. A lógica é a expectativa de o framework de chamada usar os argumentos ByRef e o wrapper unir isso.

O código é um exemplo de como navegar e recuperar dados NoSQL por código Python.

A implementação em Python usa um bloco try-except para interromper problemas de ambiente de execução do código Python e propagar esses detalhes das informações de erros da maneira normal de volta ao aplicativo do cliente. Isso pode ser ativado ao descomentar a linha que começa com "#x=10/0".

Por exemplo, o erro interrompido retornado ao cliente:

[SQLCODE: <-400>:<Fatal error occurred>]
[%msg: <Python general error 'alwo.PyProcTest::GetNotesFetchPy:Traceback (most recent call last):
                   File "PyProcTest", line 21, in GetNotesFetchPy
                                                                 ZeroDivisionError: division by zero
                    '>]

///Ref: Defining and Using Class Queries
///https://docs.intersystems.com/iris20232/csp/docbook/DocBook.UI.Page.cls?KEY=GOBJ_queries
Classalwo.PyProcTest [ Abstract ]
{
 
///<example>
///do $SYSTEM.SQL.Shell()
///call alwo.PyProcTest_GetNotes('D')
///</example>
QueryGetNotes(tabNameAs%String) As%Query(ROWSPEC = "Tab:%String,NoteId:%Integer,NoteText:%String") [ SqlName = PyProcTest_GetNotes, SqlProc ]
{
}
 
///ObjectScript due to ByRef signature
ClassMethodGetNotesExecute(ByRefqHandleAs%Binary, tabNameAs%String = "") As%Status
{
  setqHandle=##class(alwo.PyNote.GetNotes.qHandle).%New()
  // Note that an empty string passed from SQL statement may appear as the null character $C(0) instead of empty string ""
  set:tabName'=$C(0) qHandle.selectedTab=tabName// may be empty string
  Quit$$$OK
}
 
///ObjectScript due to ByRef signature
ClassMethodGetNotesFetch(ByRefqHandleAs%Binary, ByRefRowAs%List, ByRefAtEndAs%Integer = 0) As%Status [ PlaceAfter = GetNotesExecute ]
{
  setrefRow=##class(alwo.PyNote.GetNotes.Row).%New()
 
  setstatus=..GetNotesFetchPy(.qHandle,.refRow)
  ifqHandle.atEnd {
    setAtEnd=1
  } else {
    // repack output row to $List format
    setRow=$ListBuild(refRow.Tab,+refRow.NoteId,refRow.NoteText)
  }
  Quitstatus
}
 
///Access to tabular view of global 2 keys deep with data at level 2 nodes
///<example>
///zwrite ^alwo.IndexBook
///
///^alwo.IndexBook("A",1)="abc"
///^alwo.IndexBook("A",2)="def"
///^alwo.IndexBook("B")=""
///^alwo.IndexBook("C")=""
///^alwo.IndexBook("D",1)="gef"
///^alwo.IndexBook("E",1)="ijk"
///^alwo.IndexBook("E",2)="lmn"
///<example>
///
///Required output
///<example>
///| Tab | NoteId | NoteText
///--------------------------
///| A   | 1      | abc
///| A   | 2      | def
///| B   | 0      |
///| C   | 0      |
///| D   | 1      | gef
///| E   | 1      | ijk
///| E   | 2      | lmn
///--------------------------
///</example>
ClassMethodGetNotesFetchPy(qHandleAsalwo.PyNote.GetNotes.qHandle, pRowAsalwo.PyNote.GetNotes.Row) As%String [ Language = python ]
{
importiris
importtraceback
ret=iris.cls('%SYSTEM.Status').OK()
try:
  # basedontheexistanceofdefinednodestheniterate
  gname="^alwo.IndexBook"
  gIterator=iris.gref(gname)
  # IterateonKey1"Tab name"whenKey2"NoteId"waspreviouslysettoempty
  if (None==qHandle.currentPage) or (""==qHandle.currentPage):
    qHandle.currentTab=gIterator.order([qHandle.currentTab])
    # changeoftabcontext
    if (None==qHandle.currentTab) or (qHandle.currentTab==""):  # norecords
      qHandle.atEnd=True
      returnret
    # defaultopenfirsttabifhasvalues
    ifqHandle.selectedTab==NoneorqHandle.selectedTab=="":
      qHandle.selectedTab=qHandle.currentTab
  pRow.Tab=qHandle.currentTab
  #x=10/0 # uncommenttodemonstrateZeroDivisionErrorhandling
  # IterateonKey2"NoteId"
  if (qHandle.selectedTab==qHandle.currentTab):
    qHandle.currentPage=gIterator.order([qHandle.currentTab,qHandle.currentPage])
    if (qHandle.currentPage!=None) and (qHandle.currentPage!=""):
      pRow.NoteId=qHandle.currentPage
      pRow.NoteText=gIterator.get([qHandle.currentTab,qHandle.currentPage])
      # checksifcurrentrecordwasthelastone
      next=gIterator.order([qHandle.currentTab,qHandle.currentPage])
      if (None==next) or (""==next):
        qHandle.currentPage=None  # causesiterateonKey1onnextmethodinvocation
exceptException:
 pErrorMessage='alwo.PyProcTest::GetNotesFetchPy:'+(traceback.format_exc())
 returniris.cls('%SYSTEM.Status').Error(2603,pErrorMessage)
returnret
}
 
///ObjectScript due to ByRef signature
ClassMethodGetNotesClose(ByRefqHandleAs%Binary) As%Status
{
  setqHandle=""
  Quit$$$OK
}
 
}

Classe helper qHandle. É inicializada em Execute e atualizada durante a recuperação de registro.

Classalwo.PyNote.GetNotes.qHandleExtends%RegisteredObject
{
 
PropertycurrentTabAs%String;
 
PropertycurrentPageAs%String;
 
PropertyselectedTabAs%String;
 
PropertyatEndAs%Integer [ InitialExpression = 0 ];
 
}

Classe helper para preencher linhas do Python com nomes legíveis:

Classalwo.PyNote.GetNotes.RowExtends%RegisteredObject
{
 
PropertyTabAs%String;
 
PropertyNoteIdAs%String;
 
PropertyNoteTextAs%String;
 
}

Espero que esse exemplo seja útil para explorar algumas novas ideias e possibilidades com o Embedded.

0
0 150
Artigo Flávio Lúcio Naves Júnior · Ago. 16, 2023 3m read

Como observado no artigo anterior, a Native API possui algumas limitações.
Portanto, fiz algumas pesquisas sobre uma interface mais semelhante a um terminal que me forneça acesso como um console ou o terminal IRIS para permitir meu $QUERY em um global e outros comandos úteis que não são suportados/mapeados na NativeAPI para ObjectScript.

As ferramentas básicas estão bem preparadas e disponíveis.

  • Connection() cria uma partição totalmente operacional e estável para mim.
  • Function() permite chamar qualquer rotina ou método de que eu preciso.
  • similar a ClassMethodValue e ClassMethodVoid
2
0 70
Artigo Flávio Lúcio Naves Júnior · Ago. 16, 2023 3m read

Esta pergunta originalmente apareceu nos comentários do post:Download globals from a particular server

Este artigo foi inspirado por uma pergunta recente feita por @Evgeny.Shvarov.
Download globals from a particular server
Não se trata de um código de "clique e execute", mas sim de um rascunho que requer ajustes para atender às suas necessidades específicas. Você precisa adicionar...

1
0 63
Artigo Danusa Calixto · Out. 27, 2022 15m read

Por que eu amo ObjectScript e por que eu acho que poderia amar Python ainda mais

Eu estava olhando o tópico de mensagens sobre o assunto "Desempenho ao construir uma string separada por vírgulas" e comecei a escrever uma resposta. No entanto, me distraí, a página foi atualizada e perdi meu texto. Não podia gastar tempo reescrevendo minha resposta, então comecei a escrever este documento em vez disso.

Comecei a escrever na linguagem MUMPS no início da minha carreira. Eu escrevia blocos de código bastante concisos e densos em que exercícios como o exemplo da string eram verdadeiros desafios. O desempenho dos servidores VAX ou Digital DEC eram aproveitados até a última gota. Planejávamos onde globais importantes ficariam em um disco. Quando o Caché foi lançado, ainda estávamos trabalhando com M/SQL. Durante um período, estive envolvido em diversas comparações de desempenho entre o Caché e o Oracle, Sybase e SQL Server. Criávamos um esquema de algumas tabelas, preenchidas com milhões de registros, e executávamos várias pesquisas no banco de dados resultante. Eu costumava escrever duas versões de declaração SQL. Uma era uma declaração SQL pura, e a outra era uma consulta personalizada que eu escrevia na definição de classe. A maior parte da lógica está no "Fetch", e eu elaborava esse método para maximizar os indíces definidos e usar ^CachéTemp para qualquer junção complexa de resultados provisórios. Às vezes, eu criava jobs de uma ou mais subconsultas que gerariam os globais temporários e resolvia as junções após a conclusão de todos os processos de jobs. O resultado poderia ser resumido da seguinte maneira:

Inserir dados no banco de dados usando SQL ou Caché Objects sempre foi mais rápido do que qualquer outro DB. Usar COS puro e conjuntos globais diretos era uma ordem de grandeza mais rápida do que SQL, Objects e qualquer outro banco de dados. O banco de dados resultante teria aproximadamente metade do tamanho de um criado por qualquer banco de dados relacional.


Ao comparar o código que escrevi no meu método "Fetch" com o código gerado pelo Caché SQL Engine, vi que usei menos variáveis, 25% menos linhas e o código ficou mais legível.

O número de leituras de blocos de dados físicos seria praticamente o mesmo que o código gerado pelo M/SQL. No entanto, o número de leituras lógicas do pool de buffers globais seria 20% menor que o M/SQL.

Recorri a todos os truques possíveis de desenvolvedores MUMPS. Usei comandos como "execute", "job" (criando threads para lidar com subconsultas em paralelo de forma eficaz), indireção e pós-condições. Recomendamos aos desenvolvedores que não usem esses recursos de linguagem para escrever código legível e capaz de ser mantido por outros desenvolvedores.

Eu inicializaria variáveis desta forma:

set (a,b,c,d)="",(x,y,z)=0,p1=+$h,p2=...,pN=99


Espremi o máximo de expressões possível em uma linha de código. Acreditávamos que a leitura de cada linha de código no "buffer de execução" resultava em um custo. Portanto, o número de linhas de código executadas sempre teve um efeito direto e inverso no desempenho.

Quando trabalho com código escrito por outro desenvolvedor e noto blocos de código que consistem em um comando definido por cada linha, fico um pouco agitado e sempre condenso essas 30 linhas em uma. Me apaixonei por Caché Objects. Vinte e cinco anos depois, esse caso durou mais que dois relacionamentos sérios e um casamento. Definições de classe, com nomes de propriedade precisos e bastante legíveis, indexação de bitmap em tudo, a menos que a indexação de busca possa fazer melhor. Quando possível, relacionamentos pais-filhos em vez de um-muitos. Uso uma chave primária personalizada em tabelas de código quando a indexação de bitmap não é necessária porque set record=$g(^global(code)) sempre será mais rápido que

set record="",rowId=$o(^IndexGlobal("IndexName",code,"")) set:$l(rowId) record=^Global(rowId)

Havia algumas formas de declarações SQL select com que o M/SQL não era compatível ou executava mal. Em geral, o Caché era 2 a 3 vezes mais rápido do que qualquer outro banco de dados.


Ao longo dos anos, o mecanismo SQL melhorou significativamente. A indexação de bitmap e iFind foi lançada. Usamos a indexação iFind nos nomes e endereços de pacientes em um banco de dados de 15 milhões de pessoas. Todos os outros campos são indexados por bitmap. Quando recebemos uma Pesquisa de Paciente de FHIR com vários parâmetros, oferecemos suporte a todos os qualificadores e operadores de especificação FHIR. Construímos uma declaração SQL que começa com uma junção em todas as entidades do paciente de FHIR, que armazenamos em classes persistentes. Estou reivindicando o uso do repositório IRIS for Health para nossa próxima fase de desenvolvimento. O IRIS teve dois lançamentos e amadureceu desde a primeira vez que trabalhei com ele na versão 2019.1. A junção é seguida por qualquer cláusula iFind em Nomes e Endereços, se especificada nos critérios de pesquisa. As cláusulas AND/OR são adicionadas para os campos nos critérios de pesquisa que sabemos serem compatíveis com índices bitmap. As pesquisas determinísticas ou probabilísticas que realizamos são tão rápidas e precisas que ainda me fazem pular de animação (na minha idade!!!).


Preciso confessar que nunca gostei do SQL quando fazia parte de um grupo cada vez menor de desenvolvedores que escreviam código MUMPS no final dos anos 80. Meus colegas foram rápidos em aderir ao Oracle ou SQL Server. Às vezes, era difícil não entrar em um estado de desespero quando ouvia opositores gritando: "O MUMPS está morto".

Então, na conferência anual do MUMPS em Dublin, acordamos em determinada manhã com um bilhete enfiado debaixo das nossas portas anunciando que a InterSystems havia comprado a DTM. Em uma conferência realizada um ano depois em Birmingham, eu estava trabalhando para a InterSystems e estávamos apresentando formulários do Visual Basic usando o Caché de dll que adquirimos quando compramos Data Tree. A Micronetics estava no estande em frente ao nosso, e eles não tinham um dll. O sistema de som deles era mais alto, mas nós havíamos vencido. Levaria mais um ano para comprarmos DSM da Digital e, por fim, MSM da Micronetics. Não havia mais como recuar.  Lembro de mostrar o M/SQL a um cliente em Birmingham que escrevia um software de contabilidade. Um dos seus clientes era o Barings Bank, que havia acabado de perder 859.000.000 GBP devido ao trader desonesto Nick Leeson. Não pude deixar de configurar meu banco de dados de exemplo para poder executar uma consulta SQL que provavelmente não era mais complexa que "SELECT sum(Total) from Accounts WHERE .... and AccountNumber="666..". A conta tinha o mesmo número daquela usada por Nick Leeson para esconder as negociações que estava fazendo para recuperar sua situação, que piorava a cada toque do sino do pregão no mercado de ações de Singapura. Lembro de ficar rindo silenciosamente, em parte pela referência implícita ao colapso do Barings Bank, mas também porque a consulta foi realmente executada, forneceu a resposta correta e não levou mais de um minuto (nenhuma dessas coisas era uma certeza na época).

Essa é a única memória que tenho de gostar do SQL. Eu lidava com vários públicos de DBA do Oracle e SQL Server e demonstrava o Caché, Caché e VB, Caché Objects e Caché SQL. O Caché Objects me encantava: tão elegante, óbvio, maleável e legível. A sintaxe de objetos (em qualquer linguagem) é muito mais natural para mim do que qualquer declaração SQL. Quando tivemos a oportunidade de pegar o esquema do aplicativo de um cliente em potencial, executá-lo através do importador SQL e traduzir o conjunto de procedimentos armazenados que o cliente em potencial incluiria no esquema em Caché Objects ou Caché Globals puro, me familiarizei muito com a leitura do plano de execução SQL e a consulta armazenada gerada. Entrei em longas conversas com Ariel Klausner sobre a consulta SQL que o cliente em potencial me deu e não estava funcionando, e essa seria a diferença entre: ver os DBAs do Oracle saindo da sala de reuniões de volta para a segurança do ajuste do índice e as 6 horas garantidas de inatividade dos sistemas todos os dias durante os backups, onde eles poderiam trazer seus aplicativos relacionais de volta à vida em prontidão para os próximos dias de negociações, ou a emoção de conquistar um cliente que havíamos buscado por meses e estava mais interessado na velocidade do Caché, Orientação de Objetos, gateways .Net ou Java e a elegância simples do CSP de corretagem. Acredito que "por que escrever aplicativos DENTRO de um ambiente de DB?" não é uma pergunta. Primeiro, crio um banco de dados para meu código e outro para meus globais e, ali mesmo, tenho um ponto de separação. Todos nós crescemos nos últimos 25+ anos pensando em Classes, Objetos, ObjectScript e Globais como todos agrupados. Argumento que, no tempo de execução, o código sendo executado no buffer é OBJ. Basicamente, o código OBJ é uma mistura de código C compilado, código de máquina puro otimizado para a plataforma em que está sendo executado e alguns resquícios da definição de classe necessária se você estiver usando $classname, $classmethod, $property e outros fatores. Grande parte do "mecanismo" do Caché ou IRIS é escrito em ObjectScript, provando que essa é uma linguagem perfeita para trabalho. É uma linguagem que pode ser explícita, abreviada e muito compacta. Ela contém todos os operadores e as construções de qualquer linguagem moderna (if, ifelse, else, try - catch, while, for [para ser justo, nossa implementação de FOR é maravilhosa: | for i="apples","pears","Nigel","Fruit" {} | for {} | for i=$$$StartGValue():$$$Increment():$$$EndValue() | ]). Se um dos primeiros criadores do MUMPS tivesse chamado $order de "$next", ele seria imediatamente reconhecível como Next(), conforme encontrado em todas as outras linguagens que iteram por uma array. $PIECE é um pouco peculiar, mas só porque todos os outros bancos de dados usam campos de tamanho fixo. O conceito das strings delimitadas usadas como construção do banco de dados é estranho para um DBA do SQL. Ao analisar o código de máquina compilado de qualquer uma das formas de banco de dados, as instruções se movem pela string, caractere por caractere, e contando o número de caracteres ou fazendo isso enquanto procuram por um delimitador de campo específico.

$list conseguiu um desempenho um pouco melhor do que $piece, mas à custa de um ou dois bytes adicionais no início de cada campo. No entanto, ainda consumiu menos espaço do que os campos de comprimento fixo. O motivo pelo qual todo código de sistema é escrito em ObjectScript até hoje é porque a linguagem é muito eficiente e legível. Além disso, quando os principais desenvolvedores do Caché/IRIS, Scott Jones, Dave McCalldon e Mo Chung, precisavam de algo onde o ObjectScript fosse inadequado, eles escreviam em C e enterravam no Kernal.


Segundo, se eu tiver uma definição de tabela e campos que exigem alguma forma de formatação ou validação em cima e além das restrições óbvias de tipo e comprimento, então quero escrever esse código e mantê-lo bastante próximo à própria definição do campo. Por que eu entraria em outra linguagem, outro ambiente, para escrever essa validação? Os bancos de dados relacionais usam procedimentos e gatilhos armazenados para lidar com essa validação usando a linguagem SQL para expressar a lógica de validação. Se encontrar um programador que prefira usar SQL para escrever lógica complexa em vez de Basic, C#, C++, ObjectScript ou Python, eu compro uma cerveja para você na próxima vez que eu passar por Viena :-)


Na universidade, aprendi a programar em Fortran e Pascal. Pascal era uma linguagem utilizável e perfeitamente legível. Como um jovem de 19 anos que ficava facilmente empolgado, o fato de que o compilador Pascal pudesse ser escrito nessa linguagem me fascinou. Mais tarde, aprendi COBOL. WTF??? No entanto, tenho um amigo que é desenvolvedor da Sage Accounting e escreve nessa linguagem porque a Sage Accounting foi escrita em COBOL. Páginas e páginas da linguagem mais detalhada, ilegível e inutilizável que já vi. Na verdade, o COBOL ainda é muito usado.

Você poderia pensar que Pascal ultrapassaria facilmente COBAL e até Basic. Mas isso não aconteceu. Por quê? É simples. Essa linguagem não era usada nos aplicativos bancários (o COBOL foi amplamente adotado em grandes aplicativos de processamento em lotes de mainframe, como Accounting). Brincávamos dizendo que os bancos não queriam comprar o modelo Caché porque não era sofisticado o suficiente. Não era porque o ObjectScript não conseguisse fazer o processamento transacional desses aplicativos bancários. Nós éramos comprovadamente mais rápidos do que qualquer tecnologia que eles estivessem usando. O problema era que eles haviam gastado muito dinheiro nos sistemas que tinham e no hardware necessário para executar esses Lotes durante a noite para os bancos abrirem às 9h do dia seguinte. As salas caras dos servidores com gás radônio e sistemas de filtragem removem até mesmo as menores partículas de poeira para que não caiam em um disco ou uma fita magnética, causando a perda de um dia inteiro de transações de contas.


Pascal deveria ter vivido mais do que o Basic e talvez isso tivesse acontecido se a Microsoft não houvesse criado o Visual Basic e entrado em competição com Delphi e Borland. O IDE parecia mesmo com o VB, mas usava Pascal em vez de Basic. Tudo isso estava acontecendo enquanto a Microsoft lançava o C#, porque eles tinham que acomodar todos os programadores de C++ e certamente não conseguiriam conquistá-los com o Basic. Eles também estavam ameaçando lançar a própria versão do Java ou remover a compatibilidade com ele, porque o Java rodar em plataformas de hardware em que o Windows nunca seria capaz de rodar era algo que os incomodava. A Microsoft só recuou quando os avanços da tecnologia tornaram o conceito de máquinas virtuais ou containers uma opção de implantação realista. Então, Pascal e Delphi simplesmente desapareceram. Fiz uma pesquisa rápida no Google e há um interpretador de Pascal para Android, então ele ainda existe.

Considerando que Pascal era uma linguagem, ao contrário do Basic, que era apenas uma linguagem de certa forma. No entanto, ele foi usado pela Microsoft para os scripts de aplicativos como o Excel e uma conexão de propriedade com o SQL Server. Isso permitiu vincular dois ambientes que eram intrinsecamente inadequados sem o incômodo de atender aos padrões ODBC e JDBC. Os padrões eram fortemente apoiados pelo Oracle, Sybase e praticamente todos que precisavam fornecer um gateway para as versões proprietárias do SQL. Assim, o Basic sobreviveu. Estou feliz por ter começado minha carreira de programador com o Pascal. Depois, tive uma grande surpresa ao escrever programas COBOL por um ano trabalhando para uma empresa de seguros. Cheguei às costas úmidas e cinzentas do Reino Unido e comecei meu primeiro emprego, que, por acaso, usava MUMPS. Toda a evolução do MUMPS para CachéObjectScript, Objects, Object Gateways, .Net e Java, Caché Basic e MultiValueBasic e agora Python. O Python fecha um ciclo e, em certo sentido, prova que o ObjectScript não é uma aberração em uma tecnologia de banco de dados não relacional rejeitada.


Caché Globals são arrays esparsas multidimensionais tão convenientes para a própria natureza dos dados de saúde que não importa o esforço do Oracle e da Microsoft em consumir esse espaço no mercado. Ainda que tenham matado Pascal e Fortran, e até Basic, eles não conseguiram matar a InterSystems. Lembro de participar de um seminário do Oracle sobre "Oracle para a Saúde". A apresentadora falava sobre o Oracle na área da saúde que, ela nos garantiu, dominaria o mercado da saúde de uma vez por todas. Levantei minha mão e perguntei: "Não é isso o que vocês afirmam em todos os grandes lançamentos há anos? Vocês fracassaram antes. Por que fariam melhor desta vez?" Ela olhou para mim e perguntou, "Quem é você?". Respondi: "Sou da InterSystems. Dominamos o mercado da saúde há 35 anos. Conseguimos isso porque nossa tecnologia nasceu no Massachusetts General Hospital. E adivinhe. Eles ainda executam os sistemas centrais nas nossas tecnologias". Nessa hora, dois seguranças corpulentos me tiraram do auditório.


Então, o Oracle com o pSQL tem o Java. A Microsoft tem o SQL Server, C# e tSQL e, quando você precisa interagir com o Java, fica sujeito ao JDBC. Da mesma forma, com Java, se você precisa conversar com tabelas do SQL Server, é obrigado a usar ODBC. Onde ficamos? Bem, chegamos à grande ideia de ter wrappers para .Net e Java. Ao usar o ObjectScript, eu instancio uma instância da Classe A. Na verdade, não importa se a Classe A é uma classe .Net, Java ou ObjectScript, porque eu instancio esses objetos usando exatamente a mesma sintaxe em todos os casos. Depois, invoco os métodos de classe ou instância para manipular os objetos. O interior desses métodos não é importante, porque a sintaxe para interagir com essas classes e os métodos é basicamente idêntica, independentemente do que elas contenham.

Junto vem o Python, que compartilha vários recursos com o ObjectScript, pois é uma linguagem interpretada, e não compilada. É bastante legível e utilizável. Assim como o Caché ObjectScript encontrou um nicho nos dados não estruturados, o Python encontrou um nicho no mundo da modelagem matemática, ML, IA e muito, muito mais. Esse não é um mundo em que C# ou Java se sintam particularmente confortáveis. Aliás, nem o ObjectScript. Assim, a InterSystems foca em fornecer funcionalidades cada vez mais poderosas para manipular grandes quantidades de dados não estruturados, além de lançar iFind e iKnow, algumas técnicas de indexação muito inteligentes e algoritmos de correspondência de probabilidade. Então, você convida o Python para se aconchegar nas nossas arrays esparsas multidimensionais, trazendo milhões de bebês .py que fazem praticamente tudo o que você precisa. É a combinação perfeita. Por precaução, esqueci de mencionar que várias arquiteturas que dominam o mundo do desenvolvimento de páginas da Web são completamente baseadas em JS (Angular.js, REACT.js, Vue.js, Bootstrap — certo, não há JS, mas ele está em tudo menos no nome — e Node.js) e Arrays de JS. O JS não vai desaparecer tão cedo. No entanto, será interessante ver o que vai acontecer com a Golang, se é que você me entende. Vi entradas baseadas em arrays de JS nas últimas competições de código. Se existe uma tecnologia que entende arrays melhor do que qualquer outra, é a IRIS.


Penso naqueles dias, sentado no meu escritório na empresa onde trabalhava no coração de Londres. Em determinado momento, a empresa estava cheia de programadores MUMPS, mas ela os transformou em programadores SQL relacionais, que depois se tornaram redundantes. Lembro da sensação de começar a questionar se minha fé no MUMPS ser simplesmente a melhor linguagem que já havia encontrado poderia estar errada. A linguagem e as empresas que construíram interpretações dessa linguagem morreriam. Isso me deixou muito triste porque, até então, havia aprendido cinco outras linguagens de programação (APL, Basic, Fortran, COBOL e Pascal) antes de descobrir o MUMPS, e o MUMPS era tão simples. Fácil de escrever, ler e implantar. Em outras palavras, era tão natural para mim quanto o inglês, e tinha um ritmo parecido com os hinos que cantávamos na escola metodista que frequentei:

Onward, Christian soldiers!

Marching as to war,

With the cross of Jesus

Going on before.

Christ, the royal Master,

Leads against the foe;

Forward into battle,

See his banners go!

Mas ele não morreu. A música mudou um pouco:

 

A bordo, Nigel Saaalllm

Voando para a guerra

Com seu cartão de crédito internacional

Indo à frente.

John, o Mestre, McCormick

Lidera contra o inimigo (Microsoft)

Avançando na batalha

Veja seus duty frees partindo

CacheObjectScript era ainda melhor que o MUMPS se isso era possível. CacheObjects parecia tão legal quando demonstrado para uma audiência pelas primeiras vezes, e CacheSQL deixou seus dias de M/SQL para trás e melhorou muito ao longo dos anos. Ainda assim, eu particularmente não gosto de escrever muito em SQL, mas encontrei um bom equilíbrio entre Objects, SQL e referências globais diretas conforme relaxei. Meu código era bastante orientado para as referências globais diretas, com um pouco de OO e o mínimo de SQL. Quando vi com os produtos que o código gerado era compacto, elegante, eficiente e legível, o equilíbrio mudou novamente. Agora, uso nomes globais diretos raramente, muito Objects e uma quantidade razoável de SQL.

Para trabalhar com Python, minha mente precisará ver padrões diferentes do meu código ObjectScript. Há muitos "abc" e outras estruturas estranhas. No entanto, depois de escrever algumas páginas de código py e me afastar, como faço ao pintar a óleo, os padrões saltarão. Assim como vejo a música como sinestesia de cores, meus programas py codificados por cores fluindo pela página também começarão a parecer aquarela ou até mesmo uma pintura a óleo pesada. Ficarei encantado, e estará tudo bem.

1
0 174
Artigo Robert Cemper · Abr. 21, 2022 2m read

Este exemplo demonstra a diferença de quando você acessa globais diretamente do
Embedded Python (ePy) comparado com o ObjectScript nativo (ISOS).

Para tornar este demo operacional, eu inicio 2 jobs em background, que irão escrever
sequencialmente na global dedicada. Um método de controle comum dispara uma execução síncrona.
De forma similar, outro método stop & view irá interromper o fluxo de dados.

 

0
0 116
Anúncio Rochael Ribeiro · Mar. 23, 2022

Olá Desenvolvedores!

Aqui estão os bonus tecnológicos para o Concurso de Globais InterSystems 2022 que irão lhes dar pontos extra na votação:

  • Implementação de Modelo de Dados - 5
  • Implementação de índice Funcional - 5
  • Uso do Data Move - 3
  • Python Nativo- 4
  • Uso de APIs de Globais  - 2
  • Uso de contêiner Docker - 2 
  • Implantação em pacote ZPM - 2
  • Demonstração Online - 2
  • Primeiro Artigo na Comunidade de Desenvolvedores - 2
  • Segundo Artigo na Comunidade de Desenvolvedores - 1
  • Validação da Qualidade de Código - 1
  • Vídeo no YouTube - 3

Vejam os detalhes abaixo.<--break-><--break->

0
0 80
Artigo Rochael Ribeiro · Fev. 21, 2022 2m read

Olá desenvolvedores!

Algumas vezes precisamos inserir ou fazer referência aos dados de classes persistentes diretamente através das globais.

E talvez muitos de vocês estejam esperando que a estrutura de dados da global com os registros seja:

^Sample.Person(Id)=$listbuild("",col1,col,2,...,coln).

Este artigo é um aviso que nem sempre isso é verdade. Não espere que sempre seja assim!

0
0 86
Artigo Rochael Ribeiro · Fev. 21, 2022 2m read

Olá Desenvolvedores!

Como você provavelmente percebeu, no IRIS 2021 os nomes das globais são randômicos.

E, se você criar classes do IRIS classes com DDL e quiser se certificar qual global foi criada, você provavelmente gostaria de escolher seu nome.

E, de fato, você consegue fazê-lo. 

Utilize WITH %CLASSPARAMETER DEFAULTGLOBAL='^GLobalName' na instrução CREATE Table para fazê-lo. Documentação. Veja o exemplo abaixo:

0
0 75
Artigo Robert Cemper · Fev. 7, 2022 1m read

Este é um pacote para exportar um arquivo de objeto global para JSON e recriá-lo recarregando a partir deste arquivo  
embeddedPython refere-se às novas tecnologias disponíveis. Deve ser entendido como um exercício de aprendizagem de
como lidar com as interfaces de linguagem.
Apenas os nós de Globals que contêm dados são apresentados no arquivo JSON gerado.

0
0 72
Artigo Robert Cemper · jan 25, 2022 1m read

Exporte um GLOBAL no formato JSON e importe também este formato. Compacto refere-se à estrutura criada.
Nós de Globals são incluídos com dados para um carregamento de dados rápido.
Mas também o código relacionado é bastante compacto.

1
0 84
Pergunta Guilherme Koerber · Set. 9, 2021

Olá comunidade!

Estou enfrentando um problema de crescimento da base, que está sendo gerado por um processo e por uma característica do Ensemble.

Ao executar o processo de limpeza das filas de mensagens o Ensemble “preserva” as Streams que fizeram parte dessas mensagens apagando somente o Header e Body. Desta forma a base de dados (de um dos namespaces) tem crescido cerca de 60GB por dia, o que vem estourando a capacidade do disco.

A InterSystems informou que isso se trata de uma característica e que está explicado nos documentos abaixo mencionados.

3
0 209
Artigo Larissa Prussak · Maio 20, 2021 1m read

No coração do IRIS e do Caché está uma arquitetura de banco de dados muito interessante que nós, na M / Gateway Developments, chamamos de "Armazenamento Global". Se você sempre quis saber mais sobre os fundamentos e recursos desse banco de dados subjacente, pode ler uma análise importante que reunimos:

https://github.com/robtweed/global_storage

Entre outras coisas, você descobrirá que:

- O armazenamento global fornece a base de um banco de dados multi-modelo completo, algo que chamamos de "NoSQL universal", embora, como você já sabe do IRIS e do Cache, ele também tem suporte relacional.

0
0 151
Artigo Robert Cemper · Dez. 14, 2020 3m read
Este é um exemplo de codificação funcionando no IRIS 2020.1 e no Caché 2018.1.3 
Ele não será sincronizado com as novas versões      
E também NÃO é atendido pelo Suporte da InterSystems!   

Globais no Caché / Ensemble / IRIS são normalmente invisíveis ao acessar o SQL
Este exemplo mostra como contornar esse limite.

Globais são apresentadas como conteúdo de uma tabela, com seus subscritos, e o conteúdo armazenado.
A global a ser visualizada é passada ao SQL por uma condição estática WHERE que
requer 3 parâmetros:

  • o nome da global (obrigatório)
  • o subscrito inicial (opcional)
  • o subscrito de parada (opcional)

Apenas fornecer o nome da global resulta em um despejo (dump) da global completo.
As globais também podem ser fornecidas com a referência estendida e, como esta é uma tabela SQL, todos os tipos de condições adicionais se aplicam.

Tome cuidado. Colocar as aspas corretamente entre SQL e Caché / Ensemble / IRIS pode ser um desafio

Exemplo:
select * from zrcc_G.dump where zrcc_G.Dump('^|"CACHE"|Sample.PersonD',2,4)=1

ID         Global           Subscrito         Valor
1   ^|"CACHE"|Sample.PersonD    (2) $lb("",792533244,"GlobaDynamics Holdings Inc.",64256,"C1787","Y5365","A5","A658","R1770","","Ironhorse,Alice D.","T3710","O3","I4011","W8367","557-37-6758",83059958205089661,"1841-01-02 00:00:00")
2   ^|"CACHE"|Sample.PersonD    (3) $lb("",862705606,"TeleLateral Associates",34553,"V8155","T8918","X9","V8732","K1167","","Eisenstien,Peter E.","H208","C8","Q2015","Q3357","702-46-8467",57275722714358892,"2020-06-23 13:27:18")
3   ^|"CACHE"|Sample.PersonD    (4) $lb("",677194559,"RoboSoft Group Ltd.",52738,"F4851","Z364","S8","O6888","O4367","","Eagleman,Clint C.","C8051","R6","V1659","C9814","664-33-8809",-53705244349891319,"2020-06-23 13:27:18")

select TOP 15 * from zrcc_G.dump where zrcc_G.Dump('^%SYS','"JOURNAL"')=1

ID  Global         Subscrito             Valor
1   ^%SYS   ("JOURNAL")            0
2   ^%SYS   ("JOURNAL","ALTDIR")   "C:\InterSystems\IRIS\altjournal\"
3   ^%SYS   ("JOURNAL","CURDIR")   "C:\InterSystems\IRIS\mgr\journal\"
4   ^%SYS   ("JOURNAL","CURRENT")  "1^C:\InterSystems\IRIS\mgr\journal\20200801.009"
5   ^%SYS   ("JOURNAL","EXPSIZE")  0
6   ^%SYS   ("JOURNAL","LAST")     "1^C:\InterSystems\IRIS\mgr\journal\20200801.009"
7   ^%SYS   ("JOURNAL","LIFESPAN","FILE")   "2,2"
8   ^%SYS   ("JOURNAL","MAXSIZE")    1073741824
9   ^%SYS   ("JOURNAL","PREFIX")   ""
10  ^%SYS   ("JOURNAL","PURGED","c:\intersystems\iris\mgr\journal\20191104.001")    "2019-11-07 17:38:30"
11  ^%SYS   ("JOURNAL","PURGED","c:\intersystems\iris\mgr\journal\20191104.002")    "2019-11-07 17:38:30"
12  ^%SYS   ("JOURNAL","PURGED","c:\intersystems\iris\mgr\journal\20191104.003")    "2019-11-07 17:38:30"
13  ^%SYS   ("JOURNAL","PURGED","c:\intersystems\iris\mgr\journal\20191104.004")    "2019-11-07 17:38:30"
14  ^%SYS   ("JOURNAL","PURGED","c:\intersystems\iris\mgr\journal\20191104.005")    "2019-11-08 08:39:47"
15  ^%SYS   ("JOURNAL","PURGED","c:\intersystems\iris\mgr\journal\20191105.001")    "2019-11-08 08:39:47"
0
0 260