搜索​​​​

清除过滤器
文章
姚 鑫 · 十二月 27, 2022

第二十六章 使用系统监视器 - 使用 ^%SYSMONMGR 管理应用程序监视器

# 第二十六章 使用系统监视器 - 使用 ^%SYSMONMGR 管理应用程序监视器 如使用 `^%SYSMONMGR` 实用程序中所述,`^%SYSMONMGR` 实用程序允许管理和配置系统监视器,包括应用程序监视器。该实用程序可以在任何名称空间中执行,使用它所做的更改只会影响启动它的名称空间。必须通过在该命名空间中启动 `^%SYSMONMGR` 来为配置的每个启动命名空间维护单独的应用程序监视器配置。 注意:在对应用程序监视器配置进行任何更改(例如激活类)之后,必须在进行更改的名称空间中重新启动系统监视器以使更改生效。 要管理应用程序监视器,请在终端中输入以下命令: ```java %SYS>do ^%SYSMONMGR ``` 然后为管理应用程序监视器输入 `5`。显示以下菜单: ```java 1) Set Sample Interval 2) Manage Monitor Classes 3) Change Default Notification Method 4) Manage Email Options 5) Manage Alerts 6) Debug Monitor Classes 7) Exit Option? ``` 输入选择的数字或按 `Enter` 退出 `Application Monitor`实用程序。 # 管理应用程序监视器 主菜单中的选项可让管理应用程序监视器,如下表所述: Option| Description ---|--- 1) Set Sample Interval|设置指标采样的时间间隔;默认值为 `30` 秒。通过设置类特定的间隔(使用“管理监视器类”子菜单上的“设置类采样间隔”选项),可以为单个类覆盖此设置。注意:如果系统监视器采样间隔(请参阅“设置系统监视器选项”子菜单中的“设置采样间隔”)长于应用程序监视类的采样间隔,则使用两个间隔中较长的一个。例如,如果系统监视器间隔为 `30`,应用程序监视器间隔为 `120`,则所有活动的应用程序监视器类每 `120` 秒采样一次;如果系统监视器间隔为 `60` 且 `%Monitor.System.LockTableclass` 间隔为 `20`,则该类每 `60` 秒采样一次。 2) Manage Monitor Classes|显示 `Manage Monitor Classes` 子菜单,它允许在运行 `Application Monitor Manager` 的命名空间中管理系统和用户定义的监视器类。 3) Change Default Notification Method |允许指定警报触发时的默认操作。除非另有说明,否则创建的任何警报都将使用此操作。 4) Manage Email Options| 显示监控电子邮件选项子菜单,它允许启用和配置电子邮件通知,以便可以在警报中指定此操作。 5) Manage Alerts|显示 Manage Alerts 子菜单,它允许为系统和用户定义的监视器类创建警报。 ## 管理监视器类 该子菜单允许管理系统和用户定义的监视器类。输入选择的号码或按 `Enter` 返回主菜单: ``` Option? 2 1) Activate/Deactivate Monitor Class 2) List Monitor Classes 3) Register Monitor System Classes 4) Remove/Purge Monitor Class 5) Set Class Sample Interval 6) Exit Option? ``` 此子菜单显示菜单项列表,可让管理系统和用户定义的类,如下表所述: Option| Description ---|--- 1) Activate / Deactivate Monitor Class|`Application Monitor` 仅对活动类进行采样。此选项可让激活一个非活动类,或停用一个活动类。可以显示在本地名称空间中注册的系统和用户定义类的编号列表,包括每个类的激活状态,方法是输入?在类上?提示,然后输入编号或类名。 2) List Monitor Classes |显示在本地命名空间中注册的系统和用户定义类的列表,包括每个类的激活状态。 3) Register Monitor System Classes |注册所有系统监视器类(`%Monitor.System.HistorySys`、`%Monitor.System.HistoryPerf` 和 `%Monitor.System.HistoryUser` 类除外)并将它们存储在本地名称空间中。仍必须使用选项 1) 激活/停用此菜单上的监控器类来激活系统类,以便开始采样。 4) Remove/Purge Class|从本地名称空间中的类列表中删除监视器类。可以显示在本地名称空间中注册的系统和用户定义类的编号列表,包括每个类的激活状态,方法是输入?在类上?提示,然后输入编号或类名。注意:此选项不会删除类,而只是从可以激活的已注册类列表中删除类的名称。要重置列表,请在此菜单上选择选项 3) `Register Monitor System Classes`。 5) Set Class Sample Interval|允许为单个类覆盖默认的应用程序监视器采样间隔,该间隔由“管理应用程序监视器”菜单的 1) 设置采样间隔选项指定。默认值为 0,这意味着该类没有特定于类的样本间隔。有关此设置、设置采样间隔设置和设置系统监视器选项中讨论的系统监视器采样间隔之间优先顺序的说明,请参阅设置采样间隔选项的说明。 6) Debug Monitor Classes|显示 `Debug Monitor Classes` 菜单,它允许启用和禁用调试以及列出错误。
文章
姚 鑫 · 二月 19, 2022

第五十九章 SQL函数 GETDATE

# 第五十九章 SQL函数 GETDATE 日期/时间函数,返回当前本地日期和时间。 # 大纲 ```java GETDATE([precision]) ``` # 参数 - `precision` - 可选-一个正整数,指定时间精度为小数秒的位数。 默认值是`0`(没有小数秒); 这个默认值是可配置的。 精度值是可选的,括号是必选的。 # 描述 `GETDATE`将此时区的当前本地日期和时间作为时间戳返回;它根据本地时间变量(如夏令时)进行调整。 `GETDATE`可以返回`%TIMESTAMP`数据类型格式(`yyyy-mm-dd hh:mm:ss.ffff`)或`%PosiTime`数据类型格式(编码的`64`位有符号整数)的时间戳。以下规则确定返回哪种时间戳格式: 1. 如果当前时间戳被提供给数据类型为`%PosiTime`的字段,则当前时间戳值将以`POSIXTIME`数据类型格式返回。例如, `WHERE PosixField=GETDATE() or INSERT INTO MyTable (PosixField) VALUES (GETDATE())` 2. 如果当前时间戳被提供给数据类型为`%TIMESTAMP`的字段,则当前时间戳值将以TIMESTAMP数据类型格式返回。其ODBC类型为`TIMESTAMP`,长度为`16`,精度为`19`,例如 `WHERE TSField=GETDATE() or INSERT INTO MyTable (TSField) VALUES (GETDATE())` 3. 如果当前时间戳是在没有上下文的情况下提供的,则当前时间戳值以`TIMESTAMP`数据类型格式返回。例如,选择`GETDATE()`。 要更改默认日期时间字符串格式,请使用带有各种日期和时间选项的`set option`命令。 `GETDATE`可以在`SELECT`语句`SELECT LIST`或查询的`WHERE`子句中使用。在设计报表时,可以使用`GETDATE`在每次生成报表时打印当前日期和时间。`GETDATE`对于跟踪活动也很有用,比如记录事务发生的时间。 可以在`CREATE TABLE`中使用`GETDATE`指定字段的默认值。`GETDATE`是`CURRENT_TIMESTAMP`的同义词,提供`GETDATE`是为了与Sybase和Microsoft SQL Server兼容。 `CURRENT_TIMESTAMP`和`NOW`函数还可以用于以时间戳或`POSIXTIME`格式将当前本地日期和时间作为时间戳返回。`CURRENT_TIMESTAMP`支持精度,现在不支持精度。 要仅返回当前日期,请使用`CURDATE`或`CURRENT_DATE`。要仅返回当前时间,请使用`CURRENT_TIME`或`CURTIME`。这些函数使用日期或时间数据类型。这些函数都不支持精度。 `TIMESTAMP`数据类型以相同的格式存储和显示其值。`POSIXTIME`数据类型将其值存储为编码的64位有符号整数。时间和日期数据类型将它们的值存储为`$HOROLOG`格式的整数。它们可以以显示格式或逻辑(存储)格式显示。可以使用`CAST`或`CONVERT`函数更改日期和时间的数据类型。 # 世界时(UTC) `GETDATE`返回当前本地日期和时间。除`GETUTCDATE`之外,所有SQL时间戳、日期和时间函数都特定于本地时区设置。`GETUTCDATE`将当前`UTC`(通用)日期和时间作为时间戳值或POSIXTIME值返回。还可以使用ObjectScript `$ZTIMESTAMP`特殊变量来获取通用的当前时间戳(独立于时区)。 # 精确到小数部分的秒 `GETDATE`可以返回多达9位的精度。 使用`precision`参数设置返回的精度的位数。 `precision`参数的默认值可以通过以下方式配置: - 使用`TIME_PRECISION`选项设置`OPTION`。 - 系统范围的`$SYSTEM.SQL.Util.SetOption()`方法配置选项`DefaultTimePrecision`。 要确定当前设置,调用`$SYSTEM.SQL.CurrentSettings()`,它显示默认的时间精度; 默认值为0。 - 进入管理门户,选择“系统管理”、“配置”、“SQL和对象设置”、“SQL”。 查看和编辑`GETDATE()`、`CURRENT_TIME`和`CURRENT_TIMESTAMP`的默认时间精度的当前设置。 指定从0到9(包括9)的整数,作为返回的十进制精度的默认位数。 默认值为0。 实际返回的精度取决于平台; 超过系统中可用精度的精度数字将作为零返回。 分数秒总是被截断,而不是四舍五入到指定的精度。 # 示例 下面的示例以`TIMESTAMP`格式返回当前日期和时间: ```sql SELECT GETDATE() AS DateTime 2022/2/12 15:39:00 ``` 下面的示例以两位精度返回当前日期和时间: ```sql SELECT GETDATE(2) AS DateTime 2022/2/12 15:39:21 ``` 下面的嵌入式SQL示例比较了本地(特定于时区)和通用(独立于时区)的时间戳: ```java ClassMethod GetDate() { &sql(SELECT GETDATE(),GETUTCDATE() INTO :a,:b) if SQLCODE'=0 { w !,"Error code ",SQLCODE } else { w !,"Local timestamp is: ",a w !,"UTC timestamp is: ",b w !,"$ZTIMESTAMP is: ",$ZDATETIME($ZTIMESTAMP,3,,3) } } ``` ```java DHC-APP> d ##class(PHA.TEST.SQLCommand).GetDate() Local timestamp is: 2022-02-12 15:40:34 UTC timestamp is: 2022-02-12 07:40:34 $ZTIMESTAMP is: 2022-02-12 07:40:34.978 ``` 下面的示例将`Orders`表中所选行中的`LastUpdate`字段设置为当前系统日期和时间。 如果`LastUpdate`是数据类型`%TimeStamp`, `GETDATE`返回当前日期和时间作为ODBC时间戳; 如果`LastUpdate`是数据类型`%PosixTime`, `GETDATE`返回当前日期和时间为编码的64位带符号整数: ```sql UPDATE Orders SET LastUpdate = GETDATE() WHERE Orders.OrderNumber=:ord ``` 在下面的例子中,`CREATE TABLE`语句使用`GETDATE`为`StartDate`字段设置一个默认值: ```sql CREATE TABLE Employees( EmpId INT NOT NULL, LastName CHAR(40) NOT NULL, FirstName CHAR(20) NOT NULL, StartDate TIMESTAMP DEFAULT GETDATE()) ```
文章
Michael Lei · 四月 13, 2022

用Globals 作为图数据库来存储和抽取图结构数据

这篇文章是对我的 iris-globals-graphDB 应用的介绍。在这篇文章中,我将演示如何在Python Flask Web 框架和PYVIS交互式网络可视化库的帮助下,将图形数据保存和抽取到InterSystems Globals中。 建议 阅读相关文档 使用 Globals 原生 SDK 介绍 PYVIS 互动式网络可视化库 第一步 : 通过使用Python 原生SDK建立与IRIS Globals的链接 #create and establish connection if not self.iris_connection: self.iris_connection = irisnative.createConnection("localhost", 1972, "USER", "superuser", "SYS") # Create an iris object self.iris_native = irisnative.createIris(self.iris_connection) return self.iris_native 第二步 : 使用 iris_native.set( ) 功能把数据保存到Globals 里 #import nodes data from csv file isdefined = self.iris_native.isDefined("^g1nodes") if isdefined == 0: with open("/opt/irisapp/misc/g1nodes.csv", newline='') as csvfile: reader = csv.DictReader(csvfile) for row in reader: self.iris_native.set(row["name"], "^g1nodes", row["id"]) #import edges data from csv file isdefined = self.iris_native.isDefined("^g1edges") if isdefined == 0: with open("/opt/irisapp/misc/g1edges.csv", newline='') as csvfile: reader = csv.DictReader(csvfile) counter = 0 for row in reader: counter = counter + 1 #Save data to globals self.iris_native.set(row["source"]+'-'+row["target"], "^g1edges", counter) 第三步: 使用iris_native.get() 功能把节点和边缘数据从Globals传递给PYVIS #Get nodes data for basic graph def get_g1nodes(self): iris = self.get_iris_native() leverl1_subscript_iter = iris.iterator("^g1nodes") result = [] # Iterate over all nodes forwards for level1_subscript, level1_value in leverl1_subscript_iter: #Get data from globals val = iris.get("^g1nodes",level1_subscript) element = {"id": level1_subscript, "label": val, "shape":"circle"} result.append(element) return result #Get edges data for basic graph def get_g1edges(self): iris = self.get_iris_native() leverl1_subscript_iter = iris.iterator("^g1edges") result = [] # Iterate over all nodes forwards for level1_subscript, level1_value in leverl1_subscript_iter: #Get data from globals val = iris.get("^g1edges",level1_subscript) element = {"from": int(val.rpartition('-')[0]), "to": int(val.rpartition('-')[2])} result.append(element) return result Step4: Use PYVIS Javascript to generate graph data <script type="text/javascript"> // initialize global variables. var edges; var nodes; var network; var container; var options, data; // This method is responsible for drawing the graph, returns the drawn network function drawGraph() { var container = document.getElementById('mynetwork'); let node = JSON.parse('{{ nodes | tojson }}'); let edge = JSON.parse('{{ edges | tojson }}'); // parsing and collecting nodes and edges from the python nodes = new vis.DataSet(node); edges = new vis.DataSet(edge); // adding nodes and edges to the graph data = {nodes: nodes, edges: edges}; var options = { "configure": { "enabled": true, "filter": [ "physics","nodes" ] }, "nodes": { "color": { "border": "rgba(233,180,56,1)", "background": "rgba(252,175,41,1)", "highlight": { "border": "rgba(38,137,233,1)", "background": "rgba(40,138,255,1)" }, "hover": { "border": "rgba(42,127,233,1)", "background": "rgba(42,126,255,1)" } }, "font": { "color": "rgba(255,255,255,1)" } }, "edges": { "color": { "inherit": true }, "smooth": { "enabled": false, "type": "continuous" } }, "interaction": { "dragNodes": true, "hideEdgesOnDrag": false, "hideNodesOnDrag": false, "navigationButtons": true, "hover": true }, "physics": { "barnesHut": { "avoidOverlap": 0, "centralGravity": 0.3, "damping": 0.09, "gravitationalConstant": -80000, "springConstant": 0.001, "springLength": 250 }, "enabled": true, "stabilization": { "enabled": true, "fit": true, "iterations": 1000, "onlyDynamicEdges": false, "updateInterval": 50 } } } // if this network requires displaying the configure window, // put it in its div options.configure["container"] = document.getElementById("config"); network = new vis.Network(container, data, options); return network; } drawGraph(); </script> 第五步: 从app.py 主文件调用上面的代码 #Mian route. (index) @app.route("/") def index(): #Establish connection and import data to globals irisglobal = IRISGLOBAL() irisglobal.import_g1_nodes_edges() irisglobal.import_g2_nodes_edges() #getting nodes data from globals nodes = irisglobal.get_g1nodes() #getting edges data from globals edges = irisglobal.get_g1edges() #To display graph with configuration pyvis = True return render_template('index.html', nodes = nodes,edges=edges,pyvis=pyvis) 下面是关于此项目的 介绍视频: 欢迎大家来我们的 Bilibili主页观看更多视频! 谢谢!
文章
姚 鑫 · 九月 30, 2021

第三十一章 SQL命令 DROP DATABASE

# 第三十一章 SQL命令 DROP DATABASE 删除数据库(命名空间)。 # 大纲 ```sql DROP DATABASE dbname [RETAIN_FILES] ``` ## 参数 - `dbname` - 要删除的数据库(命名空间)的名称。 - `RETAIN_FILES` - 可选-如果指定,则不会删除物理数据库文件(`IRIS.DAT`文件)。默认情况下,删除`.dat`文件以及命名空间和其他数据库实体。 # 描述 `DROP DATABASE`命令删除命名空间及其关联的数据库。 指定的`dbname`是包含相应数据库文件的命名空间和目录的名称。指定`dbname`作为标识符。命名空间名称不区分大小写。如果指定的`DBNAME`命名空间不存在, IRIS将发出`SQLCODE-340`错误。 `DROP DATABASE`命令是一个特权操作。 在使用`DROP DATABASE`之前,必须以`%Admin_Manage`资源的用户身份登录。 用户还必须拥有用于例程和全局数据库定义的资源的`READ`权限。 如果不这样做,将导致`SQLCODE -99`错误(权限冲突)。 使用`$SYSTEM.Security.Login()`方法为用户分配适当的权限: ```java DO $SYSTEM.Security.Login("_SYSTEM","SYS") &sql( ) ``` 必须具有`%Service_Login:Use`权限才能调用`$SYSTEM.Security.Login`方法。 不管权限如何,`DROP DATABASE`都不能用于删除系统命名空间。尝试这样做会导致`SQLCODE-342`错误。 `DROP DATABASE`不能用于删除当前正在使用或连接到的命名空间。尝试这样做会导致`SQLCODE-344`错误。 还可以使用管理门户删除命名空间。依次选择System Administration、Configuration、System Configuration、Namespaces以列出现有的`Namespace`。单击要删除的命名空间的删除按钮。 ## RETAIN_FILES 如果指定此选项,则保留物理文件结构;删除数据库及其关联的命名空间。执行此操作后,后续尝试使用`DBNAME`将导致以下结果: - `DROP DATABASE`不带`RETAIN_FILES`无法删除此物理文件结构。相反,它会导致`SQLCODE-340`错误(未找到数据库)。 - `DROP DATABASE WITH RETAIN_FILES`还会导致`SQLCODE-340`错误(找不到数据库)。 - `CREATE DATABASE`无法创建同名的新数据库。相反,它会导致`SQLCODE-341`错误(无法为数据库创建数据库文件)。 - 尝试使用此命名空间会导致``错误。 ## 服务器初始化和断开代码 服务器初始化代码和服务器断开代码可以通过`$SYSTEM.SQL.Util.SetOption("ServerInitCode",value)`和`$SYSTEM.SQL.Util.SetOption("ServerDisconnectCode",value)`方法分配给命名空间。 可以使用相应的`$SYSTEM.SQL.Util.GetOption()`方法选项来确定当前值。 使用`DROP DATABASE`或其他接口删除命名空间,将删除这些`Server Init Code`和`Server Disconnect Code`值。 因此,删除并重新创建名称空间需要重新指定这些值。 # 示例 ```sql CREATE DATABASE DocTestDB ON DIRECTORY 'c:\InterSystems\IRIS142\mgr\DocTestDB' ``` ```sql DROP DATABASE DocTestDB RETAIN_FILES ```
文章
姚 鑫 · 九月 23, 2022

第四十一章 使用多个 IRIS 实例(一)

# 第四十一章 使用多个 IRIS 实例(一) 可以在单个主机系统上安装和运行多个 `IRIS®` 数据平台实例。每个实例都是一个独特的、独立的 `IRIS` 环境。 # 管理 IRIS 实例 有许多方法可以连接和管理 `IRIS` 实例,它可能是安装在给定系统上的几种方法之一。两种最常用的方法如下: - 安装在 `Windows` 系统上的每个 `IRIS` 实例在系统托盘中都有自己的启动器,除其他选项外,还可以: - 通过打开管理门户、 `Terminal`和 `Studio` 开发者客户端连接到实例。 - 启动、停止和重新启动实例。 - 打开用户和开发人员文档。 从启动器中,还可以管理多个远程 `IRIS` 实例,包括但不限于运行远程备份、编辑配置设置以及创建和编译远程对象和例程。 - `iris command` 在操作系统命令行上执行 iris 命令可让管理访问 `IRIS` 实例,其中包括其他选项,可以: - 使用 `Terminal`连接到实例。 - 启动、停止和重新启动实例。 - 显示有关该实例以及系统上安装的其他实例的信息。 要在远程服务器上使用 `iris` 命令,请使用 `Telnet` 或 `SSH` 客户端;要将它与容器化实例一起使用,请在容器内使用它,或者使用 `docker exec` 命令从容器外部运行它。 # 连接到 `IRIS` 实例 `Terminal` 是一个命令行,可以在 `IRIS` 实例的任何命名空间中使用。使用命令 `iris terminal instname` 打开正在运行的实例的终端,其中 `instname` 是在安装时为实例指定的名称。容器化实例通常被命名为 `IRIS`。 使用在安装期间提供的密码或创建的帐户使用预定义的用户帐户之一登录。显示的提示指示登录命名空间,例如: ```java # iris terminal IRISHealth Node: intersystems2588, Instance: IRIS27 Username: admin Password: ******** USER> ``` 要退出终端并关闭窗口,请输入命令 `halt`。 当使用`docker exec` 命令打开容器化实例的终端时(如在部署和探索 `IRIS` 中使用 终端进行交互中所述),将自动以 `irisowner` 身份登录,无需进行身份验证。 在 `Windows` 系统上,必须从其位置( `IRIS` 实例的 `install-dir\bin` 目录)执行命令,或在命令中包含完整路径,例如 `c:\InterSystems\IRIS27\bin\iris terminal IRISHealth` .可以执行给定实例的二进制文件以连接到该实例或另一个;无论哪种方式,实例名称都是必需的。
文章
姚 鑫 · 十二月 31, 2023

第十一章 创建Callout Library - 使用 J 链接类型传递标准计数字符串

# 第十一章 创建Callout Library - 使用 J 链接类型传递标准计数字符串 # 使用 `J` 链接类型传递标准计数字符串 `iris-callin.h` 头文件定义了计数字符串结构 `IRIS_EXSTR`,表示标准 `IRIS` 字符串。此结构包含一个字符元素数组(`8` 位、`16` 位 `Unicode` 或 `32` 位 `wchar t`)和一个指定数组中元素数量的 `int` 值(最多字符串长度限制): ```java typedef struct { unsigned int len; /* length of string */ union { Callin_char_t *ch; /* text of the 8-bit string */ unsigned short *wch; /* text of the 16-bit string */ wchar_t *lch; /* text of the 32-bit string */ /* OR unsigned short *lch if 32-bit characters are not enabled */ } str; } IRIS_EXSTR, *IRIS_EXSTRP; ``` C Datatype| Input |In/Out |Notes ---|---|---|--- IRIS_EXSTR| 1j or j |1J or J| 8 位国家字符的标准字符串 IRIS_EXSTR |2j or n| 2J or N|16 位 Unicode 字符的标准字符串 IRIS_EXSTR| 4j |4J |32 位字符的标准字符串 wchar_t 字符 `IRIS_EXSTR` 数据结构由 `Callin API`(低级 `InterSystems` 函数调用库)中的函数进行操作。有关详细信息,请参阅使用 `Callin API` 中的“`Callin` 函数参考”。尽管名称相似,`Callin API` 和 `$ZF`标注接口是完全独立的产品)。 以下函数用于创建和销毁 `IRIS_EXSTR` 实例: - `IrisExStrNew[W][H`] — 为字符串分配请求的存储量,并使用长度和指向该结构的值字段的指针填充 `IRIS_EXSTR` 结构。 - `IrisExStrKill` — 释放与 `IRIS_EXSTR` 字符串关联的存储。 这是一个 `Callout` 库,它使用所有三种链接类型来返回数字字符串: ### 使用 `J` 连接传递字符串 以下三个函数均生成一个随机整数,将其转换为最多包含 `6` 位数字的数字字符串,并使用 `J` 链接返回字符串 。 ```java #define ZF_DLL // Required when creating a Callout library. #include #include #include #include int get_sample_L(IRIS_EXSTRP retval) { // 8-bit characters Callin_char_t numstr[6]; size_t len = 0; sprintf(numstr,"%d",(rand()%1000000)); len = strlen(numstr); IRISEXSTRKILL(retval); if (!IRISEXSTRNEW(retval,len)) {return ZF_FAILURE;} memcpy(retval->str.ch,numstr,len); // copy to retval->str.ch return ZF_SUCCESS; } int get_sample_LW(IRIS_EXSTRP retval) { // 16-bit characters unsigned short numstr[6]; size_t len = 0; swprintf(numstr,6,L"%d",(rand()%1000000)); len = wcslen(numstr); IRISEXSTRKILL(retval); if (!IRISEXSTRNEW(retval,len)) {return ZF_FAILURE;} memcpy(retval->str.wch,numstr,(len*sizeof(unsigned short))); // copy to retval->str.wch return ZF_SUCCESS; } int get_sample_LH(IRIS_EXSTRP retval) { // 32-bit characters wchar_t numstr[6]; size_t len = 0; swprintf(numstr,6,L"%d",(rand()%1000000)); len = wcslen(numstr); IRISEXSTRKILL(retval); if (!IRISEXSTRNEW(retval,len)) {return ZF_FAILURE;} memcpy(retval->str.lch,numstr,(len*sizeof(wchar_t))); // copy to retval->str.lch return ZF_SUCCESS; } ZFBEGIN ZFENTRY("GetSampleL","1J",get_sample_L) ZFENTRY("GetSampleLW","2J",get_sample_LW) ZFENTRY("GetSampleLH","4J",get_sample_LH) ZFEND ``` 注意:始终终止 `IRIS_EXSTRP` 输入参数 在前面的示例中,始终调用 `IRISEXSTRKILL(retval)` 以从内存中删除输入参数。即使参数不用于输出,也应该始终这样做。如果不这样做可能会导致内存泄漏。
文章
姚 鑫 · 二月 12, 2023

第七十四章 使用 irisstat 实用程序监控 IRIS - 查看 irisstat 输出

# 第七十四章 使用 irisstat 实用程序监控 IRIS - 查看 irisstat 输出 # 查看 `irisstat` 输出 可以立即查看 `irisstat` 数据(通过终端)或重定向到输出文件以供以后分析。查看数据的最常见方法是: 注意:当 `IRIS` 被强制关闭时,`irisstat` 会运行以捕获系统的当前状态。作为紧急关闭程序的一部分,输出被添加到消息日志中。 ## irisstat 文本文件 `irisstat` 报告可以重定向到文件而不是终端,如果想收集一组 `IRIS` 工具(诊断报告任务、`IRISHung` 脚本、`^SystemPerformance` 实用程序)未提供的一组 `irisstat` 选项,这可能很有用或者如果在运行这些工具时遇到问题。 ## 诊断报告任务 诊断报告任务会创建一个包含基本信息和高级信息的 HTML 日志文件,InterSystems 全球响应中心 (WRC) 可以使用该文件来解决系统问题。 注意:诊断报告任务不能在挂起的系统上运行;如果系统挂起,请参阅本附录中的 `IRISHung` 脚本。 ## IRISHung 脚本 `IRISHung` 脚本是一个操作系统工具,用于在 `IRIS` 实例挂起时收集系统数据。位于 `install-dir\bin` 目录中的脚本名称是特定于平台的,如下表中指定: Platform| Script name ---|--- `Microsoft Windows`| `IRISHung.cmd` `UNIX®/Linux` |`IRISHung.sh` `IRISHung` 脚本应以管理员权限运行。与诊断报告任务一样,`IRISHung` 脚本运行 `irisstat` 两次,间隔 `30` 秒,以防状态发生变化,并将报告与其他收集的数据一起打包到一个 `html` 文件中。从 `IRISHung` 获取的 `irisstat` 报告使用以下选项 ```java irisstat -e2 -f-1 -m-1 -n3 -j5 -g1 -L1 -u-1 -v1 -p-1 -c-1 -q1 -w2 -E-1 -N65535 ``` `IRISHung` 还运行仅使用 `-S2` 选项的第三个 `irisstat`,它将其写入一个单独的输出部分,称为“自诊断”。 `-S2` 选项导致可疑进程留下小型转储;因此,运行 `IRISHung` 可能会收集有关负责挂起的特定进程的信息,而简单地强制实例关闭不会收集此信息。 此外,`IRISHung` 生成的 `irisstat` 输出文件通常非常大,在这种情况下,它们被保存到单独的 `.txt` 文件中。请记住在收集输出时检查这些文件。 ## `^SystemPerformance Utility` `^SystemPerformance` 实用程序收集有关 `IRIS` 实例及其运行平台的详细性能数据。在 `IRIS` 内运行一段可配置的时间,在该时间间隔内收集样本,并在完成时生成报告。
文章
姚 鑫 · 八月 29, 2024

第十一章 创建和使用策略 - 在运行时指定策略

# 第十一章 创建和使用策略 - 在运行时指定策略 # 在运行时指定策略 对于 `IRIS Web` 客户端,可以指定运行时要使用的策略;这将覆盖任何策略配置类。要在运行时指定策略,请设置 `Web` 客户端实例的 `PolicyConfiguration` 属性。该值必须具有以下形式: ```java Configuration class name:Configuration name ``` 其中,配置类名称是策略配置类的完整包和类名,如本主题前面所述,配置名称是该类中策略的 `` 元素的 `name` 属性的值 # 抑制不支持的策略的编译错误 默认情况下,当编译配置类时,如果配置包含 `IRIS` 不支持的任何策略表达式, `IRIS` 会发出错误。要避免此类错误,请在配置类中包含以下内容: ```java Parameter REPORTANYERROR=0; ``` 当从 `WSDL` 生成 `Web` 客户端或 `Web` 服务时,如果 `IRIS` 还生成配置类,则会将此参数设置包含在该类中。 只要有一个受支持的策略替代方案,就可以忽略不受支持的替代方案。 ## 编辑生成的策略 如果从 `WSDL` 生成配置类,并且 `WSDL` 位于 `IRIS` 此实例的外部,则必须编辑配置类以包含有关要使用的证书和 `SSL/TLS` 配置的信息。或者可以在运行时指定此信息。 下表给出了详细信息: If the Generated Policy Includes ...| Do the following ... ---|--- `` |对于附加到客户端的策略,请执行以下操作之一:按照添加扩展属性中的说明编辑此元素。按照指定客户端要使用的 `SSL/TLS` 配置中所述指定 `SSL/TLS` 配置的名称。对于附加到服务的策略,不需要进行任何更改。 `` |对于附加到客户端的策略,请执行以下操作之一:按照添加 `InterSystems` 扩展属性中所述编辑其中的 ``元素。检索凭证集并添加包含的证书,如在运行时添加证书中所述。无论如何,这必须是客户端拥有的凭证集。对于附加到服务的策略,无需进行任何更改。 `` |执行以下操作之一:按照添加 扩展属性中所述编辑其中的 ``元素。检索凭证集并添加包含的证书,如在运行时添加证书中所述。无论哪种情况,这都必须是服务拥有的凭证集。 ``| 可选择添加 `cfg:Lifetime` 属性,如添加 扩展属性中所述。默认生存期为 `5` 分钟。
文章
姚 鑫 · 一月 27

第九章 D - E 开头的术语

[toc] # 第九章 D - E 开头的术语 #### 显示格式 (display format) **对象(Objects)** 属性的显示格式是用于显示和输入数据的格式。 #### 分布式数据库 (distributed database) **系统** 存储在网络中多台计算机上的数据库。当在分布式数据库环境中使用`IRIS` 时,位于一台计算机上的 `ObjectScript` 例程可以在网络中其他计算机的文件保护限制内访问全局。 #### DMNNET **系统** 处理来自网络的传入全局请求的`IRIS` 进程。它是在系统状态(`%SS`)显示或系统操作实用工具中的进程面板上表示网络守护进程的名称。 #### 点语法 (dot syntax) **对象(Objects)** 点语法允许获取和设置属性值以及执行方法。它还允许从引用对象访问被引用和嵌入对象的属性和方法。 # 以 E 开头的术语. #### 可嵌入类 (embeddable class) **对象(Objects)** 从可嵌入(序列化)类派生的对象可以在内存中独立存在,但在存储到数据库时,只作为持久对象中的数据存储。参见` %SerialObject` 方法。 #### 内嵌 HTML (embedded HTML) **ObjectScript** 直接嵌入在 `ObjectScript` 方法或宏例程中的 `HTML`。内嵌 `HTML` 必须包含在 `&html` 语句中。 #### 内嵌对象 (embedded object) **对象(Objects)** 可嵌入类的实例。内嵌对象在内存中是独立的对象,但只能作为持久对象中的数据嵌入存储。 #### 内嵌 SQL (embedded SQL) **InterSystems SQL** 直接嵌入在 `ObjectScript` 方法或宏例程中的 `SQL`。内嵌 `SQL` 必须包含在 `&sql()` 语句中。 #### 空字符串 (empty string) **系统** 逻辑上没有任何字符的字符串,通常在文本中表示为 ""。有些资料也将其称为“空值字符串”。 不同语言对空字符串的表示方式不同,这决定了它是否以及如何在计算机内存中占用实际空间。例如,在 `ObjectScript` 中,`""` 不会占用内存空间,而在 `SQL` 中会。还要注意,虽然一个字符串中没有字符,它仍然是一个字符串,并且在不同的上下文中可能会与 `NULL`(未分配)值不同对待。 例如,在以下 `ObjectScript` 代码中: ```java New A New B Set A = "" Write A Write B 第一个 Write 语句成功执行(尽管视觉上不明显),而第二个会导致 错误。 ``` #### 封装 (encapsulation) **对象(Objects)** 封装通过呈现一个公开接口来隐藏类的内部细节,该接口概述了类允许的所有交互,而不展示执行这些操作所使用的任何细节。
文章
Jingwei Wang · 十月 9, 2024

在 IRIS 中使用 Foreign Table(外部表)

Foreign Table 的概念 Foreign Table 是 IRIS SQL 中一种特殊类型的表。它不代表 IRIS 本地全局管理的数据,而是投射出来的,由 “外部服务器 ”管理的外部数据。从 SQL 的角度来看,外部表与普通表一样,可以在查询中使用,没有任何特定限制。 在数据编织中可以帮助整合不同的来源的数据,以支持各种应用、分析并提供智能洞察力。 Foreign Table 和 Linked Table 的区别 Linked Table Lined Table 不能读取外部文件 对于 JDBC 和 ODBC 的数据源是分开的 Foreign Table 可以读取外部文件 不局限于同一类型的数据源 Foreign Table 的用例 当某个数据集时由外部应用程序在外部数据库中管理,而你的 IRIS 查询需要在该外部数据集中查找某些内容时,您可以使用某种 ETL 流程将数据加载到 IRIS 中,但如果外部数据经常更新,而你的查询需要访问当前的版本,那么这个过程可能会变得很棘手。可以通过 Foreign Table 将数据投射到 IRIS 并在查询时从外部源检索当前数据来解决这个问题。 当您要使用某些基于文件的大型数据集,您只需要偶尔查询一下,用来建立报告或训练模型。由于文件过大,加载文件可能会很麻烦,而且大型数据会占用昂贵的存储空间,而且一旦文件更新,就必须清除并重新加载。Foreign Table可以保持 SQL 查询对数据的可访问性,而不会增加 IRIS 的存储空间占用,也可以会保持最新数据。 Foreign Table 操作步骤 创建外部服务器 CREATE FOREIGN SERVER Sample.PostgresDB FOREIGN DATA WRAPPER JDBC CONNECTION 'postgresConnection' 创建 Foreign Tables CREATE FOREIGN TABLE Sample.AccountTeam ( TeamID BIGINT, Name VARCHAR(50), CountryCode VARCHAR(10) ) SERVER Sample.PostgresDB TABLE 'Sample.Teams' 查询 SELECT t.Name, COUNT(m.*) FROM Sample.AccountManager m JOIN Sample.AccountTeam t ON m.TeamID = t.TeamID WHERE t.CountryCode = 'UK' AND m.Salary > 100000 GROUP BY t.Name 删除 Foreign Tables DROP FOREIGN TABLE Example.MyForeignTable 删除外部服务器 DROP FOREIGN SERVER Example.PostgresDB CASCADE ( CASCADE 选项用来删除外部服务器和该外部服务器上定义的所有外部表 ) Foreign Table 演示 如果您想获取更详细的对于Foreign Table的演示,您可以参考 InterSystems 2023 峰会上面的演示示例,该示例使用docker,示例代码请参考Github ,安装后访问http://localhost:8888/
文章
姚 鑫 · 三月 30, 2021

第十四章 使用SQL Shell界面(一)

# 第十四章 使用SQL Shell界面(一) # 执行SQL的其他方式 可以使用`$SYSTEM.SQL.Execute()` 方法从Terminal命令行执行一行SQL代码,而无需调用SQL Shell。以下示例显示如何在终端提示下使用此方法: ```sql DHC-APP>SET result=$SYSTEM.SQL.Execute("SELECT TOP 5 name,dob,ssn FROM Sample.Person") DHC-APP>DO result.%Display() Name DOB SSN yaoxin 54536 111-11-1117 xiaoli 111-11-1111 姚鑫 63189 111-11-1112 姚鑫 63189 111-11-1113 姚鑫 50066 111-11-1114 5 Rows(s) Affected ``` 如果SQL语句包含错误,则`Execute()`方法成功完成;否则,该方法无效。 `%Display()`方法返回错误信息,例如: ```java USER>DO result.%Display() [SQLCODE: :] [%msg: < Field 'GAME' not found in the applicable tables^ SELECT TOP ? game ,>] 0 Rows Affected USER> ``` `Execute()`方法还提供了可选的`SelectMode`、`Dialect`和`ObjectSelectMode`参数。 InterSystems IRIS支持许多其他编写和执行SQL代码的方法 这些包括: - 嵌入式SQL:嵌入ObjectScript代码中的SQL代码。 - 动态SQL:使用`%SQL`。 从ObjectScript代码中执行SQL语句的语句类方法。 - 管理门户SQL接口:使用Execute Query接口从InterSystems IRIS管理门户执行动态SQL。 # 调用SQL Shell 可以使用`$SYSTEM.SQL.Shell()`方法在终端提示符中调用SQL Shell,如下所示: ```java DO $SYSTEM.SQL.Shell() ``` 或者,可以使用%SQL作为一个实例调用SQL Shell。 Shell类,如下所示: ```java DO ##class(%SQL.Shell).%Go("IRIS") ``` 或 ```java SET sqlsh=##class(%SQL.Shell).%New() DO sqlsh.%Go("IRIS") ``` 无论如何调用,SQL Shell都会返回SQL Shell提示符,如下所示: ```java [SQL]termprompt>> ``` 其中[SQL]是指在SQL Shell中,termprompt是配置的终端提示符,`>>`是指SQL命令行。 默认情况下,SQL Shell提示符如下所示:`[SQL]nsp>>`,其中`“nsp”`是当前命名空间的名称。 ```java DHC-APP>DO $SYSTEM.SQL.Shell() SQL Command Line Shell ---------------------------------------------------- The command prefix is currently set to: . Enter q to quit, ? for help. DHC-APP>> > 1>> 1>>SELECT TOP 5 name,dob,ssn FROM Sample.Person 2>> 2>>q DHC-APP>>q ``` 在这个提示符下,可以使用以下任一Shell模式: - 单行模式:在提示符下键入一行SQL代码。 结束SQL语句,按`“Enter”`。 默认情况下,这将准备并执行SQL代码(这称为立即执行模式)。 对于查询,结果集显示在终端屏幕上。 对于其他SQL语句,将在终端屏幕上显示SQLCODE和行数值。 - 多行模式:在提示符下按Enter。这使进入多行模式。可以键入多行SQL代码,每个新行提示均指示行号。 (空行不会增加行号。)要结束多行SQL语句,请键入GO并按Enter。默认情况下,这既准备并执行SQL代码。对于查询,结果集显示在终端屏幕上。对于其他SQL语句,SQLCODE和行计数值显示在终端屏幕上。 多行模式提供以下命令,可以在多行提示符下键入以下命令,然后按Enter:`L`或`LIST`列出到目前为止输入的所有SQL代码。 `C`或`CLEAR`删除到目前为止输入的所有SQL代码。 `C n`或`CLEAR n`(其中`n`是行号整数)以删除特定的SQL代码行。 `G`或`GO`准备和执行SQL代码,然后返回单行模式。 `Q`或`QUIT`删除到目前为止输入的所有SQL代码并返回单行模式。这些命令不区分大小写。发出命令不会增加下一个多行提示的行号。打`?`在多行提示符处列出了这些多行命令。 为了准备一条SQL语句,SQL Shell首先验证该语句,包括确认指定的表存在于当前名称空间中,并且指定的字段存在于表中。如果不是,它将显示适当的SQLCODE。 如果该语句有效,并且具有适当的特权,则SQL Shell会回显SQL语句,并为其分配一个序号。无论您是否更改名称空间和/或退出并重新进入SQL Shell,这些数字在终端会话期间都将按顺序分配。这些分配的语句编号允许重新调用以前的SQL语句,如下所述。 也可以使用`DO Shell^%apiSQL`.在终端提示下调用SQL Shell。 要列出所有可用的SQL Shell命令,请输入`?`。在SQL提示下。 要终止SQL Shell会话并返回到`Terminal`提示符,请在SQL提示符下输入`Q`或`QUIT`命令或`E`命令。 SQL Shell命令不区分大小写。 以下是使用默认参数设置的示例SQL Shell会话: ```java DHC-APP>DO $SYSTEM.SQL.Shell() SQL Command Line Shell ---------------------------------------------------- The command prefix is currently set to: . Enter q to quit, ? for help. DHC-APP>>SELECT TOP 5 Name,Home_State FROM Sample.Person ORDER BY Home_State 1. SELECT TOP 5 Name,Home_State FROM Sample.Person ORDER BY Home_State Name Home_State xiaoli 姚鑫 姚鑫 姚鑫 姚鑫 5 Rows(s) Affected statement prepare time(s)/globals/lines/disk: 0.0523s/45502/270281/2ms execute time(s)/globals/lines/disk: 0.0004s/225/2915/0ms --------------------------------------------------------------------------- DHC-APP>>q ``` 以下是使用默认参数设置的多行SQL Shell会话: ```java DHC-APP>DO $SYSTEM.SQL.Shell() SQL Command Line Shell ---------------------------------------------------- The command prefix is currently set to: . Enter q to quit, ? for help. DHC-APP>> > 1>>SELECT TOP 5 2>>Name,Home_State 3>>FROM Sample.Person 4>>ORDER BY Home_State 5>>GO 2. SELECT TOP 5 Name,Home_State FROM Sample.Person ORDER BY Home_State Name Home_State xiaoli 姚鑫 姚鑫 姚鑫 姚鑫 5 Rows(s) Affected statement prepare time(s)/globals/lines/disk: 0.0002s/18/1168/0ms execute time(s)/globals/lines/disk: 0.0003s/225/2886/0ms --------------------------------------------------------------------------- ``` ## GO命令 SQL Shell `GO`命令执行最新的SQL语句。在单行模式下,`GO`重新执行最近执行的SQL语句。在多行模式下,`GO`命令用于执行多行SQL语句并退出多行模式。单行模式下的后续`GO`将重新执行先前的多行SQL语句。 ## 输入参数 SQL Shell支持使用`“?”`输入参数的使用SQL语句中的字符。每次执行SQL语句时,系统都会提示指定这些输入参数的值。必须以与`“?”`相同的顺序指定这些值字符出现在SQL语句中:第一个提示为第一个`“?”`提供一个值,第二个提示为第二个`“?”`提供一个值,依此类推。 输入参数的数量没有限制。可以使用输入参数将值提供给`TOP`子句,`WHERE`子句,并将表达式提供给`SELECT`列表。不能使用输入参数将列名提供给`SELECT`列表。 可以将主机变量指定为输入参数值。在输入参数提示下,指定一个以冒号(:)开头的值。该值可以是公共变量,ObjectScript特殊变量,数字文字或表达式。然后,SQL Shell会提示“这是文字(Y / N)吗?”。在此提示下指定N(否)(或仅按Enter)意味着将输入值解析为主机变量。例如,`:myval`将被解析为局部变量myval的值; `:^ myval`将被解析为全局变量`^myval`的值; `:$HOROLOG`将被解析为`$HOROLOG`特殊变量的值; `:3`将被解析为数字3; `:10-3`将被解析为数字`7`。在此提示符下指定Y(是)表示将输入值(包括冒号)作为文字提供给输入参数。 ## 执行ObjectScript命令 在SQL Shell中,可能希望发出一个ObjectScript命令。例如,通过使用`SET $NAMESPACE`命令将InterSystems IRIS命名空间更改为包含要引用的SQL表或存储过程的命名空间。可以使用SQL Shell!命令或OBJ命令以发出由一个或多个ObjectScript命令组成的ObjectScript命令行。 (OBJ是OBJECTSCRIPT的缩写。)!,OBJ和OBJECTSCRIPT命令是同义词。以下示例显示了这些命令的用法: ```java %SYS>DO $SYSTEM.SQL.Shell() SQL Command Line Shell ---------------------------------------------- The command prefix is currently set to: . Enter q to quit, ? for help. [SQL]%SYS>>! SET oldns=$NAMESPACE SET $NAMESPACE="USER" WRITE "changed the namespace" changed the namespace [SQL]USER>>OBJ SET $NAMESPACE=oldns WRITE "reverted to old namespace" reverted to old namespace [SQL]%SYS>> ``` OBJ命令之后的其余命令行被视为ObjectScript代码。 !之间不需要空格。和ObjectScript命令行。可以在SQL Shell单行模式或SQL Shell多行模式下指定OBJ命令。以下示例在USER名称空间中定义的表上执行SELECT查询: ```java %SYS>DO $SYSTEM.SQL.Shell() SQL Command Line Shell ---------------------------------------------- The command prefix is currently set to: . Enter q to quit, ? for help. [SQL]%SYS>> > 1>>OBJ SET $NAMESPACE="USER" 1>>SELECT TOP 5 Name,Home_State 2>>FROM Sample.Person 3>>GO /* SQL query results */ [SQL]USER>> ``` 请注意,OBJ语句不会增加SQL行数。 在SQL Shell多行模式下,在返回行时将执行OBJ命令,但是直到指定`GO`才发出SQL语句。因此,以下示例在功能上与先前的示例相同: ```java %SYS>DO $SYSTEM.SQL.Shell() SQL Command Line Shell ---------------------------------------------- The command prefix is currently set to: . Enter q to quit, ? for help. [SQL]%SYS>> > 1>>SELECT TOP 5 Name,Home_State 2>>FROM Sample.Person 3>>OBJ SET $NAMESPACE="USER" WRITE "changed namespace" changed namespace 3>>GO /* SQL query results */ [SQL]USER>> ``` 以下示例使用OBJ命令定义主机变量: ```java USER>DO $SYSTEM.SQL.Shell() SQL Command Line Shell ---------------------------------------------- The command prefix is currently set to: . Enter q to quit, ? for help. [SQL]USER>> > 1>>SELECT TOP :n Name,Home_State 2>>FROM Sample.Person 3>>OBJ SET n=5 3>>GO ``` ## 浏览命名空间 SQL Shell支持BROWSE命令,该命令显示在当前名称空间中定义或可从其访问的架构,表和视图。该显示包括多个级别的提示。要返回上一个提示级别,请在提示时按`Return`键。名称区分大小写。 1. 在SQL Shell提示符下键入BROWSE,以列出当前名称空间中的架构。 2. 在“架构:”提示下,按名称或编号选择一个架构。这将列出架构中的表和视图。 3. 在“表/视图:”提示下,按名称或编号选择一个表(T)或视图(V)。这将显示表信息,然后显示选项列表。 4. 在“选项:”提示下,按编号选择一个选项。可以使用此选项列出为表定义的字段或映射。 指定选项1(按名称表示的字段)或选项2(按数字表示的字段)以显示“Field:”提示。指定选项3(地图)以显示“Map:”提示。 5. 在`“Field:”`提示下,按数字或名称选择一个字段,或指定*以列出所有字段。这列出了详细的字段信息。 在`“Map:”`提示下,按数字或名称选择地图,或指定`*`列出所有Map。这列出了详细的Map信息。 ## CALL 命令 可以使用SQL Shell发出SQL `CALL`语句来调用SQL存储过程,如以下示例所示: ```java DHC-APP>>CALL Sample.PersonSets('G','NY') 3. CALL Sample.PersonSets('G','NY') Dumping result #1 Name DOB Spouse Gallant,Thelma Q. 45767 94 Gibbs,Mark S. 37331 13 Goldman,Will H. 59069 10 Gomez,Mo Q. 55626 55 Gore,Alfred M. 42991 13 Gore,Fred X. 32391 6 Grabscheid,Jocelyn B. 59676 79 7 Rows(s) Affected Dumping result #2 Name Age Home_City Home_State Chadbourne,Danielle G. 34 Pueblo NY Eastman,Clint G. 4 Miami NY Pape,Linda M. 71 Vail NY Peterson,Janice N. 49 Islip NY Schaefer,Jocelyn V. 93 Zanesville NY 5 Rows(s) Affected statement prepare time(s)/globals/lines/disk: 0.0043s/2153/15795/0ms execute time(s)/globals/lines/disk: 0.0015s/315/7829/0ms --------------------------------------------------------------------------- ``` 如果指定的存储过程在当前名称空间中不存在,则SQL Shell会发出`SQLCODE -428`错误。 如果指定的输入参数多于存储过程中定义的参数,则SQL Shell会发出`SQLCODE -370`错误。可以使用文字(`“字符串”`),主机变量(`:var`)和输入参数(`?`)的任意组合为存储过程指定参数值。 可以在`CALL`语句中使用主机变量,如以下示例所示: ```java [SQL]USER>>OBJ SET a="G",b="NY" [SQL]USER>>CALL Sample.PersonSets(:a,:b) ``` - 可以在`CALL`语句中使用输入参数(`“?”`字符),如以下示例所示: ```java [SQL]USER>>CALL Sample.PersonSets(?,?) ``` 当执行`CALL`语句时,SQL Shell会提示为每个输入参数提供一个值。 ## 执行SQL脚本文件 SQL Shell `RUN`命令执行一个SQL脚本文件。脚本文件的类型由`DIALECT`设置确定。 `DIALECT`的默认值为IRIS(InterSystems SQL)。
文章
Qiao Peng · 三月 17, 2024

生成式大语言模型和检索增强生成

近来生成式大语言模型掀起了革命性的AI浪潮。生成式大语言模型是什么原理?我们怎么在业务中利用它? 一. 大语言模型的工作原理 生成式大语言模型是生成式人工智能底层的机器学习模型,是一种用于自然语言处理的深度学习模型。 人工智能、机器学习与大语言模型的关系如下图: 1.1 为什么我们称之为大语言模型? 大语言模型的“大”体现在多个方面: 首先,模型尺寸巨大,尤其是它的参数数量。例如GPT3有1750亿的参数; 其次,大语言模型是在巨大的算力基础上,基于海量语料进行训练的。例如Meta的Llama 2 的训练数据达到了两万亿个词(token); 再次,大语言模型是为解决通用问题,而非特定问题构建的。 1.2 大语言模型是怎么训练的? 大语言模型是事先训练好的模型。 训练时,大语言模型基于各种语料 - 人类知识库(例如Wikipedia)、公共数据集、网络爬虫数据,让模型进行“填空”练习,并经过人工编辑和“校对” 训练出来的,需要成千上万的GPU建立集群进行训练。根据Meta的信息,其Llama 2 的训练数据达到了两万亿个token,上下文长度为4096,对话上也是使用100万人类标记的数据微调。 运行时,训练产生的大语言模型可以在小的多的硬件上运行。 1.3 大语言模型的机器学习算法 冰冻三尺,非一日之寒;滴水穿石,非一日之功。生成式大语言模型能够落地经历了相当漫长的技术积累与进步。 大语言模型使用的机器学习算法是优化过的神经网络(Neural Network)。 神经网络发明于上世纪40-50年代,本质上是一个曲线拟合算法,通过拟合多个、多层的Softplus(曲线)、ReLU(Rectified Linear Unit 折线)、Sigmoid(对数线),实现对任意曲线的拟合。 “神经网络”名字听起来很高大上,但并不是脑科学的产物。因为发明时,觉得算法中每个节点像神经元、每个连线像神经触突,因此称为神经网络。 它很早就应用于自动控制领域。后来发展出多种神经网络算法,例如用于图像识别的卷积神经网络(CNN)、很早就用于语言学习的递归神经网络(RNN)… 在大语言模型成熟前,自然语言处理进化出过众多的技术,例如词袋、词汇矢量化、基于递归神经网络的模型、超长短期记忆网络(LSTM)… 但都在能力和算力上有众多缺陷,无法用于有实用价值的内容生成领域。 虽然它们不能实现实用化的内容生成,但为内容生成式大语言模型落地打下了基础,也是我们了解大语言模型前必须了解的预备知识。 1.3.1 分词(Tokenization) 词汇是语言模型分析的最小语义单位,所以第一步要把语句拆分成词汇(token)。分词并不简单,例如中文语句的分词就无法通过空格区分。所以用于大语言模型的分词算法也是基于海量语料训练出来的。 而基于大语言模型的内容生成,就是基于当前的所有token,预测下一个token,从而产生完整的内容。 1.3.2 词汇和语句的矢量化 机器学习算法基本只能处理数字,无法处理文本、声音、图像等非数字内容。所以要处理语言,需要对语句进行矢量化的表达,将其转换为数字。 拿我们常玩的一个游戏做解释:一个人在头脑里想象一个事物,让另一个人猜。另一个人可以问任何问题,但第一个人只能回答是和否。例如问:是动物吗?答:是;问:是哺乳动物吗?答:不是。问:有脚吗?答:是。 这个游戏的过程就是用不同维度来验证和归类一个事物,最终可以让这个事物在不同的维度上得以表达,即这个事物在一个高维度矢量空间上可以得到一个定位(矢量),同时相近的概念在矢量空间互相接近。 大语言模型通过大规模语料训练用神经网络将每个词汇在一个高维度空间矢量化,得到表达矢量的数组,将词汇矢量化到如下示意的矢量空间中: 这里的矢量化出来的是密集矢量,即每个维度上都不是0,且维度数固定,从而用更少的字节中存在更多的信息,因此在计算上的利用成本更低。相较于稀疏矢量的例子,例如书籍的归类:科学、言情、教育、音乐… ,词汇和语句的矢量结果密集度高的多,因此是密集矢量。 而语句矢量化在词汇矢量化的基础上,要将词汇在句子中的顺序信息加入,从而将“小明追老虎”和“老虎追小明”这两个词汇完全相同但语义完全不同的句子在矢量化输出上能够加以区分。 1.3.3 基于大语言的矢量化模型 将词汇和语句矢量化,是迈向我们如今看到的生成式大语言模型的第二步。 不同的语言矢量化模型生成的密集矢量维度数是不一样的,越高的维度数的密集矢量需要越大的计算资源和越大的内存消耗。下面是一些常见的矢量化语言模型和它们的维度数: 模型 维度数量 BERT (Bidirectional Encoder Representations from Transformers) 768或1024 GPT (Generative Pre-trained Transformer) 768或1600 Word2Vec 300 USE (Universal Sentence Encoder) 512 MiniLM 384 1.3.4 矢量相似度查询 词汇和句子矢量化后,怎么找到相似的词汇和句子? 对两个矢量进行相似度查询,就是计算两个矢量间的“距离”。有很多算法,如下图中所示的这些常见算法。 在大规模、高维度矢量数据库中查找近义词,如果采用与矢量记录逐一计算相似度的方法,将需要巨大的计算量,其效率并不能满足实用的性能需求。 而实际需求并不需要精确的相似度,因此出现了近似近邻算法(Approximate Nearest Neighbors - ANN)解决效率问题。ANN有多种算法,例如Annoy (Approximate Nearest Neighbors Oh Yeah)、 HNSW (Hierarchical Navigable Small World)。 下图是Annoy算法的示意图: 在矢量数据集中随机找2个矢量,计算出一个矢量平面到2个矢量的距离相同,从而将矢量数据集分割成2个空间;然后再在每个空间里重复上面的过程,直到分割后的空间里矢量数量与目标相似度矢量数量一致(例如我们希望得到返回矢量数量为10个以内的相似度结果集,那么如果空间内的矢量数小于等于10,就停止上述过程);从而我们得到一个决策树,今后可以用这个决策树进行矢量相似度查询,显然会快很多。 因为Annoy是基于最初的随机选择的2个矢量开始决策树构建的,如果这2个矢量本身就是高度相似的,那这2个矢量永远不会被一个矢量相似度查询要求同时命中,从而带来显著的误差。怎么办?可以随机多选几组初始矢量,从而形成多棵决策树的决策森林,提高ANN的精度。 可见ANN是大规模矢量检索查询的核心。 1.3.5 生成式大语言模型 递归神经网络(recurrent neural network - RNN)很早就应用到自然语言处理领域,之后出现了RNN改进模型LSTM (Long short-term memory),它们按顺序处理输入语句的词汇,并行能力不足,而且越高阶的神经网络需要的算力越高,达不到实用化的性能需求。 在2017年Google一个小团队(Transformer八子)发表了一篇论文 - Attention Is All You Need, 阐述了一类特殊的神经网络 – 基于注意力(Attention)机制的Transformer。它的注意力机制根据输入数据的长度执行固定步骤的计算,并且对输入数据的词汇(token)是并行计算的,它奠定了实用的生成式大语言模型的基础。这个团队的成员后大多离开了Google,并创立或加入了目前市场上几个主要生成式大语言模型。 在Transformer并行处理能力和越来越强大的GPU并行算力加持下,生成式大语言模型终是水到渠成,可以说是大力出奇迹! 当然Transformer模型具备多个特殊能力支撑内容生成能力。下面这张图解释了Transformer模型的4个核心特性:词汇矢量化(Word Embedding)、词汇在语句中位置的矢量化叠加(Positional Encoding)、自我注意力(Self-Attention)和残值连接(Residual Connections)。可见它其实构建在前面出现的技术基础之上。 借助这个新神经网络模型思路,众多大厂发布了自己的生成式大语言模型,如下面列出的这些著名的大语言模型。它们的宣传中常常强调其百亿级、甚至千亿级的参数: 模型 厂商 参数 GPT OpenAI (Microsoft) 1750亿 Bard/Gemini Google 18亿,32.5亿 PaLM2 Google 3400亿 Llama 2 Meta 70亿,130亿,700亿 Claude 2/3 Anthropic (Amazon) 未披露 Stable Beluga Stability AI 70亿,130亿,700亿 Coral Cohere 未披露 Falcon Technology Innovation Institute 13亿,75亿,400亿,1800亿 MPT Mosaic 70亿,300亿 往往参数规模越大,其生成的内容越精确和越富有创造力。那么这些参数指什么?无论是什么样的大语言模型,它们底层都是神经网络,这些参数主要就是指神经网络中的权重和偏差。 二. 大语言模型应用中的问题和检索增强生成 从机制上,生成式大语言模型并不神秘。虽然它展现出了强大的理解能力甚至“创造力”,但它有以下几个问题: 它的知识来自于训练语料,并不知道所有知识。例如GPT-4 截止训练数据的时间是2022年1月份,对于后来的世界一无所知,更不可能知道您的机构中的未开放数据。 它是基于通用数据训练的,对于特定领域往往训练不足。 它的内容生成机制是使用神经网络逐词预测出回答中的下一个词从而构成完整的语句。因此它本质上不会拒绝回答任何问题,虽然人类限制它回答诸如如何制作病毒类的问题。结合它的“无知”和“创造力”,对不知道的问题,它也能一本正经地胡说八道,这就是生成式大语言模型的“幻觉”。 生成式大语言模型的“幻觉”在目前的应用中非常常见。例如我问了Bing Copilot一个关于“什么是InterSystems IRIS互联互通套件?”的问题,它不懂但没有拒绝回答,而且回答地相当“幻觉”: 如果想在我们自己的业务中直接应用生成式大语言模型,让它提供患者教育,或者回复患者的预约查询、亦或回答患者关于他/她自己的用药注意事项?显然不靠谱。 是不是可以用我们自己的数据进行训练?一来很多大模型都不是开放的,无法自己训练;二来相信大家都没有训练大语言模型的昂贵算力。 怎么解决这个问题? 大语言模型其实有三次“训练”机会: 预先训练就是大语言模型厂商通过海量语料进行的训练,我们干不了; 调优训练需要基于开放的大语言模型,算力成本也不低; 所以我们可以通过“提示”,让生成式大语言模型给我们想要的答案。 我又试了一次让Bing Copilot回答“什么是InterSystems IRIS互联互通套件?”,不过这次,我给了它提示,让它先读读关于InterSystems IRIS互联互通套件介绍的网页。这次它回答得相当到位: 也就是通过合适的提问,把本地数据提示给生成式大语言模型,从而让它可以准确回答而不会产生幻觉。 检索增强生成基于问题先在本地数据检索,将相关结果提示给生成式大语言模型,从而获得靠谱的回答,这就是检索增强生成(Retrieval Augmented Generation – RAG)。 这里的本地数据检索,是基于大语言的矢量相似度检索。所以,需要借助矢量数据库,对本地的数据矢量化保存、并提供基于问题的矢量相似度查询,从而基于问题给出最匹配的本地数据。 这里是完整的检索增强生成流程示意图,分为2个过程: 1. 基于本地数据建立矢量知识库的过程 预先建立知识库, 将本地文档切分成文本段 使用矢量化语言模型对数据矢量化 将矢量保存到矢量知识库 2. 借助本地矢量知识库和外部大语言模型回答问题的过程 使用矢量化模型将问题矢量化 在矢量数据库中检索与问题相关的矢量记录 将匹配的数据(知识)作为上下文组织到完整的问题与提示中,向大语言模型提问。例如提示模版是:请仅使用以下上下文回答问题 从大语言模型得到回答 由此可见,检索增强生成至少需要以下3个技术组件: 矢量数据库 – 用于本地数据的矢量化保存和矢量化查询 矢量化语言模型 – 用于将本地数据和问题矢量化 内容生成语言模型 – 用于基于问题和上下文生成自然语言回答 矢量化语言模型、内容生成语言模型都有很多选择,根据需要可以选择能部署到本地的模型、也可以选择厂商提供的云服务。 而矢量数据库是保存本地知识数据的矢量化版本的,市面上常见的是一些nonSQL的专用数据库,也就是说需要将本地数据迁移到矢量数据库,并专门学习其数据操作的API。 可以预见,生成式大语言模型的能力将迅速进化,但本地的知识和数据并不会以如此快的速度发生变化。因此RAG将本地的知识和数据通过矢量化与生成式大语言模型集成,借助其不断提升的强大能力又无需被任何一个模型绑架,将是一个合理的解决方案。 三. InterSystems IRIS的内容生成架构 InterSystems IRIS是应用在众多行业的通用数据平台,并在2024版本中加入了对矢量存储和查询的支持,无需将IRIS中已经保存的本地知识数据迁移到别的矢量数据库中,从而消除数据迁移时间差、额外部署矢量数据库的运维成本,同时降低敏感数据泄露风险、确保遵循特定行业中对数据迁移监管的要求。而InterSystems IRIS作为一个具有互操作能力的数据平台,可以轻松集成大语言模型,并建立和管理检索增强生成的pipeline,降低RAG的技术实现复杂度。 3.1 IRIS的矢量存储和矢量查询 IRIS提供矢量数据类型,它被完全集成在IRIS多模型的架构中,尤其使用SQL就可以完整使用矢量存储和查询。 例如要创建含有矢量类型字段vec的表: CREATE TABLE t (txt VARCHAR(1000), vec VECTOR(INT, 200)); 向矢量字段vec中插入数据: INSERT INTO t VALUES (‘…’, TO_VECTOR(‘1,2,3,…’, INT)); 这里的矢量数据是需要通过调用矢量化模型产生的。 基于矢量相似度查询最接近的10条记录: SELECT TOP 10 * FROM FROM ( SELECT t.*, VECTOR_DOT_PRODUCT(vec, TO_VECTOR(…)) AS similarity FROM t ) ORDER BY similarity DESC; 3.2 IRIS的矢量索引 IRIS进一步提供了更易使用的矢量索引:无需创建矢量字段,直接在现有数据表上就可以创建声明式的矢量索引,并自动调用集成的矢量化模型,从而使用SQL就可以免代码方式进行开发。 创建矢量索引 – 通过索引对title、author和article这3个字段组合进行矢量化: CREATE INDEX Vec ON MyNews(Title, Author, Article) AS VectorIndex(MODEL=‘BERT’); 执行矢量查询 – 查询与条件最近似的3条记录: SELECT TOP 3 * FROM MyNews WHERE Category = ‘NYT’ ORDER BY MyTable_VecSim(%ID, ‘climate change’); 3.3 基于IRIS构建完整的RAG方案 基于最新发布的InterSystems IRIS 2024.1,和部署到本地的矢量化模型(all-MiniLM-L12-v2)、内容生成模型(llama2),我构建了一个RAG原型: 这里IRIS实例即是保存本地数据的数据平台,也是本地数据的矢量化数据库,从而避免了数据的跨平台迁移。而全SQL的数据操作能力,让构建在自己数据上的检索增强生成方案能快速落地。 现在就把生成式大语言模型集成到您自己的业务中吧!注:本文中的部分图片来自StatQuest、medium、wikipedia和weaviate。
公告
Jeff Liu · 六月 29, 2021

2021年6月,开发者社区更新。

开发者们好! 这是我们在2021年6月改进开发者社区的一个版本。主要特点是。 改进的月度摘要直接信息的全新设计(包括新功能)。请看下面的细节。 改进后的月度摘要数字无处不在! 我们已经收集了DC网站的一些基本统计数据,并将关键数字添加到月度摘要中。 现在你可以很容易地看到我们社区的范围。 私信的新设计 迎接一个全新的、改进的私信(DM)版本 想象一下社区内成熟的电子邮件--我们的成员可以通过DM轻松地相互沟通,为几个成员创建对话,就某些主题进行聊天,等等。 创建你的个人或群组聊天,添加主题,了解你的信息的观点,以及更多... 那么,有什么新内容呢? 我们增加了一个带有几个标签的侧边菜单,以方便在DM中导航: 要使用新功能,请选择一条/多条/所有信息。 新功能将出现在顶部。 1. 你可以通过以下方式之一将信息添加到你的书签中。 将鼠标悬停在信息主题上时,点击星星图标 选择一个或几个信息,并点击顶部的 "添加到书签"。 2. 你也可以使任何信息成为未读信息,这样你就可以在以后回来回复它。只要选择你想要的信息并点击 "标记为未读"。 所有新的信息都有一个蓝点标记。 对于移动版本,我们已经开发了一个现代和轻量级的设计。 你可以通过点击用户的头像来轻松选择信息,使用顶部的一个功能。 在下拉菜单中的标签之间移动。 我们希望你能喜欢我们的更新! 欢迎提交 新的改进请求和错误报告. 敬请关注!
文章
Michael Lei · 六月 23, 2021

最低限度的监控和警报解决方案

InterSystems 数据平台包括了用于系统监视和警报的实用程序及工具,但对于不熟悉构建于 InterSystems 数据平台(又名 Caché)的解决方案的系统管理员来说,他们需要知道从何处下手以及需要配置什么。 本指南以在线文档和开发者社区帖子为参考,介绍了实现最低限度的监视和警报解决方案的途径,以及如何启用和配置以下组件: 1. **Caché Monitor:**扫描控制台日志并发送电子邮件警报。 2. **System Monitor:**监视系统状态和资源,根据固定参数生成通知(警报和警告),同时跟踪整体系统运行状况。 3. **Health Monitor:**对主要的系统和用户定义指标进行采样,并将它们与用户可配置的参数和既定的标准值进行比较,在样本超过适用或学习的阈值时生成通知。 4. **History Monitor:**维护性能指标和系统使用情况指标的历史数据库。 5. **pButtons:**每天按计划收集操作系统指标和 Caché 指标。 请记住,本指南是最低配置,所包含的工具灵活且可扩展,因此可在需要时提供更多功能。 本指南跳过了文档,让您直接上手。 您需要更深入地研究文档才能充分利用监视工具,同时,请考虑将本指南作为启动和运行的速查表。 ---- # 1. Caché Monitor 控制台日志 `(install-directory/mgr/cconsole.log)` 必须被监视,可以通过第三方工具扫描日志文件,或者像我们这样使用附带的 Caché Monitor 实用工具将警报发送到一个电子邮件地址。 控制台日志是其他监视工具(包括 Caché System Monitor 和 Caché Health Monitor)用于编写警报和通知的中央存储库。 > 至少将 Caché Monitor 配置为向一个电子邮件发送警报。 使用 ^MONMGR 实用工具管理 Caché Monitor。 ## Caché Monitor 基本设置 Caché Monitor 扫描控制台日志,并根据可配置的消息严重级别生成通知。 通知通过电子邮件发送到您配置的收件人列表。 默认扫描周期为每 10 秒一次,但可以更改。 > 提示:将 Caché Monitor 警报严重级别配置为 1(警告、严重和致命条目)。 如果您发现收到的警报太多,可以降回到警报级别 2(严重和致命条目)。 当 60 秒内有一系列条目来自一个给定进程时,只会针对第一个条目生成通知,然后暂停一小时。 因此,当出现问题时,必须进行调查。 因为没有新消息并不表示事件已过去。 此规则的例外是 [Caché Monitor 错误和陷阱](http://docs.intersystems.com/latest/csp/docbook/DocBook.UI.Page.cls?KEY=GCM_monitor#GCM_monitor_errors)中列出的控制台日志条目,会针对其中所有条目生成通知。 [有关完整的配置详细信息,请参见 ^MONMGR 的在线文档。](http://docs.intersystems.com/latest/csp/docbook/DocBook.UI.Page.cls?KEY=GCM_monitor#GCM_monitor_errors) ## Caché Monitor 速查表 启用 Caché Monitor 不需要很多操作。 确保 Monitor 已启动,然后设置电子邮件选项。 %SYS>d ^MONMGR 1) Start/Stop/Update MONITOR 2) Manage MONITOR Options 3) Exit Option? **1** 1) Update MONITOR 2) Halt MONITOR 3) Start MONITOR 4) Reset Alerts 5) Exit Option? **3** Starting MONITOR... MONITOR started 1) Update MONITOR 2) Halt MONITOR 3) Start MONITOR 4) Reset Alerts 5) Exit Option? **** 设置警报严重级别。 1) Start/Stop/Update MONITOR 2) Manage MONITOR Options 3) Exit Option? **2** 1) Set Monitor Interval 2) Set Alert Level 3) Manage Email Options 4) Exit Option? **2** Alert on Severity (1=warning,2=severe,3=fatal)? 2 => **1** 设置电子邮件选项,您可能需要联系 IT 部门以获取电子邮件服务器的地址。 任何有效的电子邮件地址都应该可用。 1) Set Monitor Interval 2) Set Alert Level 3) Manage Email Options 4) Exit Option? **3** 1) Enable/Disable Email 2) Set Sender 3) Set Server 4) Manage Recipients 5) Set Authentication 6) Test Email 7) Exit Option? 确保在设置后测试电子邮件(选项 6)。 ## Caché Monitor 示例 Caché System Monitor 针对高 CPU 利用率生成了一个严重级别为 2 的条目,该条目已发送到 cconsole.log: 03/07/18-11:44:50:578 (4410) 2 [SYSTEM MONITOR] CPUusage Alert: CPUusage = 92, 95, 98 (Max value is 85). 同时也向 Caché Monitor 电子邮件收件人发送了一封电子邮件,其内容与 console.log 相同,主题行为: [CACHE SEVERE ERROR yourserver.name.com:instancename] [SYSTEM MONITOR] CPUusage Alert: CPUusage = 92, 95, 98 (Max value is 85). ## Caché Monitor 更多提示 在开发者社区的另一篇文章的评论中,Aric West 提示可以在发件人电子邮件中嵌入更多信息,例如,不要只设置一个有效的电子邮件,而是将发件人或收件人设置为:"某个名字" \ ---- # Caché System Monitor 工具 Caché System Monitor 是一系列监视工具的汇总,通过 `^%SYSMONMGR` 实用工具进行配置。 如简介中所述,为实现最低限度的监视解决方案,我们将配置: - System Monitor - Health Monitor - History Monitor 顺带说一下,是的,名称 _System Monitor_ 很令人烦恼地重载了其父名称 _Caché System Monitor_。 Caché System Monitor 和 Health Monitor 通知和警报会发送到控制台日志,使 Caché Monitor(在上一节中设置)可以在事件发生时生成电子邮件。 [有关 Caché System Monitor 的所有深入详细信息,请参见在线文档。](http://docs.intersystems.com/latest/csp/docbook/DocBook.UI.Page.cls?KEY=GCM_healthmon) ---- **警告说明:**您还将在 ^%SYSMONMGR 菜单中看到 **Application Monitor**。 本指南中不会配置 Application Monitor。 本指南中介绍的工具和实用程序对系统性能的影响可以忽略不计,然而 Application Monitor 有一些类是此规则的例外。 [有关详细信息,请参见 ^PERFMON 实用工具的文档](http://docs.intersystems.com/latest/csp/docbook/DocBook.UI.Page.cls?KEY=GCM_perfmon)。 如果您使用 Application Monitor,则必须先在非生产系统上测试,因为运行任何时长的 ^PERFMON 都可能对性能产生重大影响。 ---- # 2. System Monitor 根据文档:“System Monitor 对重要的系统状态和资源使用指标(例如 ECP 连接的状态和使用中的锁表的百分比)进行采样,并根据固定状态和阈值生成通知(警报、警告和‘状态正常’消息)”。 [文档中有 System Monitor 状态和资源指标](http://docs.intersystems.com/latest/csp/docbook/DocBook.UI.Page.cls?KEY=GCM_healthmon_sysmon_alerts)的列表。 例如:日志空间(日志目录中的可用空间): - 少于 250 MB = _警告_ - 少于 50 MB = _警报_ - 警告/警报后大于 250 MB = _正常_ ## System Monitor 基本设置 System Monitor 警报和警告会写入控制台日志,因此请确保 Caché Monitor 设置为发送电子邮件警报(上一节)。 使用 ^SYSMONMGR 实用工具管理 System Monitor。 默认情况下,当实例运行时,System Monitor 也一直运行;可以使用 ^%SYSMONMGR 将其停止,但是当实例下次启动时,它会自动再次启动。 默认情况下,System Monitor 具有以下可以更改的设置: - 每 30 秒获取一次传感器指标。 - 仅将警报、警告和消息写入 System Monitor 日志。 System Monitor 还维护单一整体系统运行状况状态,当运行 `ccontrol list` 等命令时可以查询或使用该状态: - 绿色(正常) - 黄色(警告) - 红色(警报) ### System Monitor 速查表 对于最低限度的监视解决方案,实际上无需任何操作,因为当实例运行时,它也一直运行。 ---- # 3. Health Monitor 根据文档:“Caché Health Monitor 通过在特定期间对一系列关键指标的值进行采样,并将这些值与配置的指标参数和这些期间的既定标准值进行比较,来监视正在运行的 Caché 实例;如果采样值过高,Health Monitor 将生成警报或警告。 例如,根据配置的 CPU 使用率最大值或者在星期一上午 9:00 至 11:30 期间采集的标准 CPU 使用率样本,如果 Health Monitor 在星期一上午 10:15 采样的 CPU 使用率过高,Health Monitor 将生成通知。” [Health Monitor 对 41 个系统传感器进行采样,文档中给出了列表和默认值。](http://docs.intersystems.com/latest/csp/docbook/DocBook.UI.Page.cls?KEY=GCM_healthmon#GCM_healthmon_overview_api_sensors) Health Monitor 警报(严重级别 2)和警告(严重级别 1)将写入控制台日志。 Health Monitor 生成: - 警报,如果在一个期间内传感器的三次连续读数大于传感器最大值。 - 警告,如果在一个期间内传感器的五次连续读数大于传感器警告值。 对于为最大值或警告值设置了条目的传感器,即使 Health Monitor 本身未启用,也会立即生成警报。 例如,为 CPU 配置的最大值为 85,警告值为 75,所以当连续 5 次的 CPU 利用率测量值超过 75% 时,会将以下通知发送到控制台日志: 1 [SYSTEM MONITOR] CPUusage Warning: CPUusage = 83 ( Warnvalue is 75). 其他传感器需要收集足够长时间的指标才能创建_图表_。 需要图表来评估指标的平均值,从而得出标准偏差 (sigma),以便在值超出正常范围时发出警报。 在一个_期间_内收集指标。 有 63 个标准期间,一个期间示例是星期一上午 9:00 至 11:30。 期间可以更改。 ## Health Monitor 基本设置 > Health Monitor 不会自动启动,需要使用 ^%SYSMONMGR 中的设置来启用它。 默认情况下,Health Monitor 在 Caché 启动后等待 10 分钟,以便系统达到正常运行状态,如果需要,可以更改此时间。 Caché Health Monitor 传感器对象带有默认值。 例如,如上文所述,_CPUPct_(系统 CPU 使用率百分比)的默认值为:基础值 50,最大值 90,警告值 80。 您可能更保守一些,并想要更改这些值,使用 ^%SYSMONMGR 可以更改这些值,例如,最大值 85,警告值 70。 现在,当 CPU 使用率达到 99% 时,我们会看到: 2 [SYSTEM MONITOR] CPUusage Alert: CPUusage = 99, 99, 99 (Max value is 85). ## Health Monitor 速查表 该速查表相当长,显示在总结后面。 ---- # 4. History Monitor [David Loveluck 在社区上有一个非常好的帖子。](https://community.intersystems.com/post/apm-using-cach%C3%A9-history-monitor)按照该帖中的说明启动 History Monitor,开始收集和评估指标。 ---- # 5. pButtons pButtons 实用工具可根据其创建的日志文件生成可读的 HTML 性能报告,其中包含操作系统和 Caché 指标。 pButtons 输出的性能指标可以被提取、绘图和评估。 例如,一天中 CPU 利用率或 Caché 数据库访问量的图表。 每天 24 小时运行 pButtons 收集是一种简单但至关重要的方法,用于收集指标以进行故障排除。 pButtons 对于趋势分析也非常有用。 以下社区文章详细介绍了 pButtons 以及如何将其计划为每天运行:[InterSystems 数据平台和性能 – 第 1 部分](https://community.intersystems.com/post/intersystems-data-platforms-and-performance-%E2%80%93-part-1) > 如文章中所述,30 秒收集间隔对于趋势分析和 24 小时报告是合适的。 还有说明用于确保您即使没有运行最新版的 Caché,也能拥有最新版的 pButtons:[InterSystems 数据平台和性能 – 如何更新 pButtons](https://community.intersystems.com/post/intersystems-data-platforms-and-performance-%E2%80%93-how-update-pbuttons)。 虽然 pButtons 主要是一个支持工具,但您可以通过快速绘制所收集的指标来获得宝贵的系统使用情况洞察:[Yape - 另一个 pButtons 提取程序(自动创建图表)](https://community.intersystems.com/post/yape-yet-another-pbuttons-extractor-and-automatically-create-charts) ---- # 总结 本帖仅触及了监控选项的皮毛,例如 Health Monitor 将以默认设置工作,但随着时间的推移,您将希望探索可自定义的选项来满足您的应用程序配置文件。 ## 接下来的方向? 如我们所见,我们将 System Monitor 和 Health Monitor 实用工具配置为将警报发送到作为中央报告位置的 cconsole.log。 我们使用了 Caché Monitor 将这些警报发送到电子邮件。 有一些第三方工具可以抓取日志并消耗非结构化的日志数据,您可能已经在组织中使用这些工具,而且也没有理由不使用它们。 如今,我看到许多客户在 VMware 上进行虚拟化。 如果您使用 vSphere,请考虑使用 Log Insight 来监视控制台日志。 在撰写本帖时(2018 年 3 月),对于您拥有的每个 vCenter Server 6.0 实例,您都有资格获取一个免费的 vRealize Log Insight for vCenter 25 OSI 许可证。 Log insight 是一个读取非结构化数据的工具,用于日志管理和分析 — 例如,您可以将其与 cconsole.log 配合使用 — 如果您对此感兴趣,请联系 VMware 以了解更多信息。 同时,我正计划在将来的帖子中展示如何将 Log Insight 与 cconsole.log 配合使用。 ---- 如果您在收集指标,您仍然需要研究它们,并了解他们的含义,我将继续发帖来展示如何解释所呈现的信息,特别是性能指标。 ---- # 应用程序性能监视 David Loveluck 在社区中有一系列关于应用程序性能监视的帖子,请在社区中搜索 APM,或者[从这里开始](https://community.intersystems.com/post/what-apm)。 ---- ## 附录:Health Monitor 速查表 本速查表展示了我们在第 3 节看到的 Health Monitor 的启动过程,并完成了传感器阈值的编辑。 首先让我们启动 Health Monitor。 %SYS>**d ^%SYSMONMGR** 1) Start/Stop System Monitor 2) Set System Monitor Options 3) Configure System Monitor Classes 4) View System Monitor State 5) Manage Application Monitor 6) Manage Health Monitor 7) View System Data 8) Exit Option? **6** 1) Enable/Disable Health Monitor 2) View Alerts Records 3) Configure Health Monitor Classes 4) Set Health Monitor Options 5) Exit Option? **1** Enable Health Monitor? No => **yes** Health Monitor is Enabled. Stop and restart System Monitor to run Health Monitor 如我们从消息中所见,导航回到第一个菜单或再次启动 ^%SYSMONMGR 来停止 System Monitor 并再次启动它,以完成这一过程。 %SYS>**d ^%SYSMONMGR** 1) Start/Stop System Monitor 2) Set System Monitor Options etc... 我们将在这里继续,以编辑 CPUPct 阈值为例。 %SYS>**d ^%SYSMONMGR** 1) Start/Stop System Monitor 2) Set System Monitor Options 3) Configure System Monitor Classes 4) View System Monitor State 5) Manage Application Monitor 6) Manage Health Monitor 7) View System Data 8) Exit Option? **6** 1) Enable/Disable Health Monitor 2) View Alerts Records 3) Configure Health Monitor Classes 4) Set Health Monitor Options 5) Exit Option? **3** 1) Activate/Deactivate Rules 2) Configure Periods 3) Configure Charts 4) Edit Sensor Objects 5) Reset Defaults 6) Exit Option? **4** 先看一下所有传感器; 1) List Sensor Objects 2) Edit Sensor Object 3) Exit Option? **1** Sensor Base Max Max M Warn Warn M -- ---- --- ----- ---- ------ CPUPct 50 80 0 70 0 CPUusage 50 85 0 75 0 CSPActivity 100 0 2 0 1.6 : : : WDWIJTime 60 0 2 0 1.6 WDWriteSize 1024 0 2 0 1.6 1) List Sensor Objects 2) Edit Sensor Object 3) Exit Option? **2** Cannot configure while System Monitor is running. 1) List Sensor Objects 2) Edit Sensor Object 3) Exit 噢,我们需要先返回并禁用 Health Monitor 和 System Monitor。 1) Enable/Disable Health Monitor 2) View Alerts Records 3) Configure Health Monitor Classes 4) Set Health Monitor Options 5) Exit Option? **1** Disable Health Monitor? No => **yes** Health Monitor is Disabled. Stop and restart System Monitor to halt Health Monitor 1) Enable/Disable Health Monitor 2) View Alerts Records 3) Configure Health Monitor Classes 4) Set Health Monitor Options 5) Exit Option?**** 1) Start/Stop System Monitor 2) Set System Monitor Options 3) Configure System Monitor Classes 4) View System Monitor State 5) Manage Application Monitor 6) Manage Health Monitor 7) View System Data 8) Exit Option? **1** 1) Start System Monitor 2) Stop System Monitor 3) Exit Option? **2** Stopping System Monitor... System Monitor stopped 好了,Health Monitor 和 System Monitor 已停止。 现在导航回到 Health Monitor 并编辑一个传感器对象。 1) Start System Monitor 2) Stop System Monitor 3) Exit Option?**** 1) Start/Stop System Monitor 2) Set System Monitor Options 3) Configure System Monitor Classes 4) View System Monitor State 5) Manage Application Monitor 6) Manage Health Monitor 7) View System Data 8) Exit Option? **6** 1) Enable/Disable Health Monitor 2) View Alerts Records 3) Configure Health Monitor Classes 4) Set Health Monitor Options 5) Exit Option? **3** 1) Activate/Deactivate Rules 2) Configure Periods 3) Configure Charts 4) Edit Sensor Objects 5) Reset Defaults 6) Exit Option? **4** 1) List Sensor Objects 2) Edit Sensor Object 3) Exit Option? **2** 输入传感器名称(如果您知道的话),否则输入“?”以显示列表。 传感器? **?** Num Sensor Threshold 1) CPUPct 2) CPUusage : : : 46) WDWIJTime 47) WDWriteSize Sensor? **1** CPUPct Base? 50 =>**** Enter either an Alert Value or a Multiplier Alert Value? 80 => **85** Setting Max Multiplier and Warn Multiplier to 0. Enter a Warn Value Warn Value? 70 => **75** Sensor object CPUPct updated. Base 50 MaxMult 0 AlertValue 85 WarnMult 0 WarnValue 75 1) List Sensor Objects 2) Edit Sensor Object 3) Exit 现在返回并启用 Health Monitor 和启动 System Monitor。 Option?**** 1) Activate/Deactivate Rules 2) Configure Periods 3) Configure Charts 4) Edit Sensor Objects 5) Reset Defaults 6) Exit Option?**** 1) Enable/Disable Health Monitor 2) View Alerts Records 3) Configure Health Monitor Classes 4) Set Health Monitor Options 5) Exit Option? **1** Enable Health Monitor? No => **yes** Health Monitor is Enabled. Stop and restart System Monitor to run Health Monitor 1) Enable/Disable Health Monitor 2) View Alerts Records 3) Configure Health Monitor Classes 4) Set Health Monitor Options 5) Exit Option?**** 1) Start/Stop System Monitor 2) Set System Monitor Options 3) Configure System Monitor Classes 4) View System Monitor State 5) Manage Application Monitor 6) Manage Health Monitor 7) View System Data 8) Exit Option? **1** 1) Start System Monitor 2) Stop System Monitor 3) Exit Option? **1** Starting System Monitor... System Monitor started 好了,工作已完成! ----
文章
姚 鑫 · 七月 16, 2021

第五章 使用文件

# 第五章 使用文件 # 使用文件 `%Library.File`类提供了几个类方法,允许对文件执行各种操作。 ## 复制文件 若要复制文件,请使用`CopyFile()`方法,该方法返回一个布尔值来指示成功或失败。 此方法采用四个参数: 1. from 从—指定源文件的名称。 2. to至—指定目标文件的名称。 3. pDeleteBeforeCopy —指定在执行复制之前是否删除目标文件(如果存在)。默认值为0。 4. return 返回—输出参数。如果为负,则包含操作系统返回的错误代码,以防方法失败 下面的第一个示例将目录`e:\temp`中的文件`old.txt`复制到`new.txt`。第二个示例将相同的文件复制到默认目录中的`new.txt`。 ```java DHC-APP>write ##class(%File).CopyFile("e:\temp\old.txt", "e:\temp\new.txt", 0, .return) 1 DHC-APP>write ##class(%File).CopyFile("e:\temp\old.txt", "new.txt", 0, .return) 1 ``` 最后一个示例失败,Windows错误代码为2,或“找不到文件” ```java DHC-APP>write ##class(%File).CopyFile("foo.txt", "new.txt", 0, .return) 0 DHC-APP>w return -2 ``` ## 删除文件 要删除文件,请使用`delete()`方法,该方法成功时返回1,失败时返回0。这个方法需要两个参数。第一个参数是要删除的文件的名称。第二个参数是输出参数。如果为负,它包含操作系统返回的错误代码,以防方法失败。 在下面的第一个示例中,方法成功了。第二个示例失败,出现Windows错误代码2或“找不到文件”。 ```java DHC-APP>write ##class(%File).Delete("e:\temp\myfile.txt", .return) 1 DHC-APP>write ##class(%File).Delete("e:\temp\myfile.txt", .return) 0 DHC-APP>w return -2 ``` 要在删除文件时匹配通配符,请使用`ComplexDelete()`方法。第一个参数指定要删除的文件的名称。第二个参数是输出参数。如果为负,它包含操作系统返回的错误代码,以防方法失败。 下面的示例删除所有带有。`e:\temp`目录中的out扩展名。 ```java DHC-APP>write ##class(%File).ComplexDelete("e:\temp\*.out", .return) 1 ``` ## 截断文件 要截断文件,请使用`truncate()`方法,该方法成功时返回1,失败时返回0。这个方法需要两个参数。第一个参数是要截断的文件的名称。第二个参数是输出参数。如果为负,它包含操作系统返回的错误代码,以防方法失败。 如果截断现有文件,方法会从文件中删除内容,但不会从文件系统中删除内容。如果截断不存在的文件,方法会创建一个新的空文件。 在下面的第一个示例中,方法成功了。第二个示例失败,Windows错误代码为5,或“访问被拒绝” ```java USER>write ##class(%File).Truncate("e:\temp\myfile.txt", .return) 1 USER>write ##class(%File).Truncate("e:\no access.txt", .return) 0 USER>write return -5 ``` ## 重命名文件 若要重命名文件,请使用`rename()`方法,该方法成功时返回1,失败时返回0。这个方法需要三个参数。第一个参数是要重命名的文件的名称,第二个参数是新名称。第三个参数是输出参数。如果为负,它包含操作系统返回的错误代码,以防方法失败。 在下面的第一个示例中,方法成功了。第二个示例失败,错误代码为183,或者“当文件已经存在时,无法创建该文件。” ```java DHC-APP>write ##class(%File).Rename("e:\temp\oldname.txt", "e:\temp\newname.txt", .return) 1 DHC-APP>write ##class(%File).Rename("e:\temp\another.txt", "e:\temp\newname.txt", .return) 0 DHC-APP>write return -2 ``` 使用此方法时,请小心指定路径,因为以下示例会将`e:\temp\oldname.txt`移动到默认目录,然后将其重命名为`newname.txt`。 ```java DHC-APP>write ##class(%File).Rename("e:\temp\oldname.txt", "newname.txt", .return) 1 ``` ## 比较文件 若要比较两个文件,请使用`Compare()`方法,如果两个文件相同,则返回布尔值1,否则返回0。该方法没有用于返回系统错误代码的输出参数。 在下面的第一个示例中,两个文件是相同的,方法返回1。在第二个示例中,两个文件不同,因此方法返回0。 ```java DHC-APP>write ##class(%File).Compare("e:\temp\old.txt", "e:\temp\new.txt") 1 DHC-APP>write ##class(%File).Compare("e:\temp\old.txt", "e:\temp\another.txt") 0 ``` 如果一个或两个文件都不存在,如下例所示,则该方法也返回0。 ```java DHC-APP>write ##class(%File).Compare("foo.txt", "bar.txt") 0 DHC-APP>write ##class(%File).Exists("foo.txt") 0 ``` ## 生成临时文件 要生成临时文件,请使用`TempFilename()`方法,该方法返回临时文件的名称。这个方法需要三个参数。第一个参数是临时文件所需的文件扩展名。第二个是生成临时文件的目录。如果未提供,该方法将在操作系统提供的临时目录中生成文件。第三个参数是输出参数。如果为负,它包含操作系统返回的错误代码,以防方法失败。 Windows示例: ```java USER>write ##class(%File).TempFilename("txt") C:\WINDOWS\TEMP\GATqk8a6.txt USER>write ##class(%File).TempFilename("txt","C:\temp") C:\temp\WpSwuLlA.txt ``` Unix示例: ```java USER>write ##class(%File).TempFilename("", "", .return) /tmp/filsfHGzc USER>write ##class(%File).TempFilename("tmp", "/InterSystems/temp", .return) /InterSystems/temp/file0tnuh.tmp USER>write ##class(%File).TempFilename("", "/tmp1", .return) USER>write return -2 ``` 在上面的第三个示例中,目录不存在,该方法失败,系统错误代码为2,或“没有这样的文件或目录。”