搜索​​​​

清除过滤器
文章
姚 鑫 · 四月 2, 2021

第十五章 使用管理门户SQL接口(一)

# 第十五章 使用管理门户SQL接口(一) 本章介绍如何在InterSystems IRIS®数据平台管理门户上执行SQL操作。 管理门户界面使用动态SQL,这意味着在运行时准备和执行查询。 Management Portal界面旨在帮助针对小型数据集开发和测试SQL代码。 它不打算用作在生产环境中执行SQL的接口。 管理门户还提供了各种配置SQL的选项。 有关使用管理门户的一般信息,请选择左上角的Help按钮。 通过使用左上角的Contact按钮,可以从管理门户向InterSystems Worldwide Response Center (WRC)报告有关InterSystems软件的问题。 # 管理门户SQL工具 InterSystems IRIS允许使用SQL工具从InterSystems IRIS管理门户检查和操作数据。 此操作的起点是Management Portal System Explorer选项。 从这里选择SQL选项。 这将显示SQL接口,它允许: - 执行SQL查询—编写和执行SQL命令。 可以对现有的表和数据执行SQL查询,创建表,或插入、更新或删除表数据。 可以编写SQL代码直接转化为一个文本框(包括选择、插入、更新、删除、创建表和其他SQL语句),检索语句的SQL历史文本框,拖拽一个表到文本框来生成一个查询(`SELECT`语句),或构成一个查询(`SELECT`语句)使用`query Builder`接口。 - 过滤模式内容——在屏幕左侧显示当前名称空间的SQL模式或这些模式的过滤子集,以及每个模式的表、视图、过程和缓存查询。 可以选择单独的表、视图、过程或缓存查询来显示其目录详细信息。 - 向导—执行向导,以执行数据导入、导出或数据迁移。 执行向导以链接到表或视图,或链接到存储过程。 - Actions -定义一个视图; 打印一个表定义的详细信息; 通过运行调优表和/或重建索引提高查询的性能; 或者通过清除不需要的缓存查询和/或删除不需要的表、视图或过程定义来执行清理。 - 打开表格——以显示模式在表格中显示当前数据。 这通常不是表中的完整数据:记录的数量和列中的数据长度都受到限制,以提供可管理的显示。 - 工具——执行以下工具之一:SQL运行时统计、索引分析器、备用显示计划、生成报告、导入报告。 - 文档—允许查看SQL错误代码列表和SQL保留字列表。 如果选择了一个表,则允许显示类文档(该表的类引用页)。 ## 选择命名空间 所有SQL操作都会在特定名称空间中进行。因此,必须首先指定要通过单击SQL接口页面顶部的 **“开关switch”** 选项要使用的命名空间。这将显示可用名称空间列表,可以从中进行选择。 可以设置管理门户默认命名空间。从管理门户选择系统管理,安全性,用户。单击所需用户的名称。这允许编辑用户定义。从“常规”选项卡中,从下拉列表中选择“启动命名”空间。单击“保存”。如果未选择启动命名空间,则会默认为%SYS.。 ## 用户自定义 许多Management Portal SQL操作都是为每个用户自动定制的。 如果在Execute Query选项卡或SQL Statements选项卡中设置了筛选器、最大值、模式或其他选项,则此用户指定的值将保留以供将来使用。 当同一个用户激活管理门户时,将显示该用户先前的设置。 重新启动InterSystems IRIS返回所有选项为默认值。 没有自定义名称空间选择。 它恢复到用户定义启动名称空间。 # 执行SQL查询 从管理门户选择System Explorer,然后选择SQL。 在页面顶部选择带有Switch选项的名称空间; 这将显示可用名称空间的列表。 要执行SQL查询,有三个选项: - Execute Query:写并执行SQL命令。 SQL命令可以是一个`SELECT`查询,也可以是一个InterSystems SQL DDL或DML语句; 语句执行时在InterSystems IRIS服务器上验证。 - Show History:收回以前运行的SQL语句,然后重新运行它,或者修改它,然后运行它。 列出所有已执行的语句,包括未成功执行的语句。 - 查询生成器:调用SQL查询生成器(它专门用于创建SELECT语句)。 在SQL Query Builder中,通过选择表、列、`WHERE`子句谓词和其他查询组件来创建SQL `SELECT`查询。 然后,可以通过单击Execute query来运行查询。 ## 编写SQL语句 Execute Query文本框不仅允许编写`SELECT`和`CALL`查询,还允许编写大多数SQL语句,包括DDL语句(如`CREATE TABLE`)和DML语句(如`INSERT`、`UPDATE`和`DELETE`)。 可以在“执行查询”文本框中指定SQL代码: - 将SQL代码键入(或粘贴)到文本框中。 SQL代码区域不给SQL文本着色,也不提供任何语法或存在验证。 但是,它确实提供了自动拼写验证。 可以使用X图标删除文本框的内容。 - 使用Show History列表选择前面的SQL语句。 选中的语句将复制到文本框中。 执行时,该语句移到Show History列表的顶部。 注意,Show History列出了之前执行的所有语句,包括那些执行失败的语句。 - 使用表拖放在文本框中构造SQL代码。 - 可以使用Query Builder(而不是Execute Query文本框)来指定和执行`SELECT`查询。 使用查询生成器执行的选择查询不会显示在“执行查询”中,也不会列出在“显示历史”中。 Execute Query文本框中的SQL代码可以包括: - ?输入参数。如果指定输入参数,例如 `TOP ? or WHERE Age BETWEEN ? AND ?`,`Execute`按钮显示查询窗口的Enter参数值,其中每个输入参数的条目字段按查询中指定的顺序。 - 空白字符。可以指定多个空格,单个和多行返回。标签键已禁用;将代码复制到SQL代码区域时,现有选项卡将转换为单个空格。线返回和未保留多个空格。 - 注释。 SQL代码区域支持单行和多行注释。在Show历史显示中保留并显示注释。在Show Plan语句文本显示或缓存查询中未显示注释。 - 返回多个结果集的查询。 在文本框中编写SQL代码后,可以单击“显示计划”按钮查看SQL代码而不执行SQL代码。如果代码有效,则显示计划显示查询计划。如果代码无效,则显示计划显示SQLCode错误值和消息。还可以使用“显示计划”按钮显示最近执行的SQL代码的此信息。 要执行SQL代码,请单击“执行”按钮。 ### 表拖放 可以通过从屏幕左侧的表列表(或视图列表)拖动表(或视图)来生成查询,并将其丢弃到执行查询文本框中。这在表中生成了选择的选项列表,以及指定表的表中的所有非隐藏字段。然后,可以进一步修改此查询并使用Execute按钮执行它。 还可以从屏幕左侧的过程列表中拖放过程名称。 ## 执行查询选项 SQL执行界面具有以下选项: - 具有`SELECT`的“选择模式下拉列表”指定查询应用于提供数据值(例如,在WHERE子句中)的格式,并在查询结果集中显示数据值。选项是显示模式(默认值),ODBC模式和逻辑模式。 具有插入或更新的选择模式下拉列表允许指定输入数据是否将从显示格式转换为逻辑存储格式。对于此数据转换,必须使用选择运行时的选择模式编译SQL代码。在执行时间时,必须将“选择模式”下拉列表设置为逻辑模式。 选择模式对于数据类型是有意义的,其逻辑存储格式与所需的显示格式(显示或ODBC)不同,例如Intersystems Iris日期和时间和Objectscript`%List`结构化数据。 - 最大字段允许限制从查询返回的数量数量。它可以设置为任何正整数,包括0.一旦设置MAX,除非显式更改,否则将该值用于会话持续时间的所有查询。默认值为1000.最大值为100,000,如果输入没有值(将MAX设置为NULL),则输入大于100,000或非数值的值,这是默认值。还可以使用顶部子句限制要返回的数据行数。 MAX对其他SQL语句没有影响,例如删除。 如果单击“更多”选项,则SQL执行界面将显示以下其他选项: - 方言:SQL代码的方言。包括“IRIS”、“Sybase”和“MSSQL”。默认为IRIS。 在InterSystems Transact-SQL (TSQL)迁移指南中描述了Sybase和MSSQL。 请注意,下次访问管理门户时,选择的方言将成为用户自定义的默认语言。 - 行号:一个复选框,指定是否在结果集中显示的每一行中包含行计数号。 行号是分配给结果集中每一行的连续整数。它只是对返回的行进行编号,它既不对应rowwid也不对应`%VID`。行号列标题名是#。默认是显示行号。 所有这些选项都是用户自定义的。 ## 显示计划按钮 Show Plan按钮在页面的文本框中显示语句文本和查询计划,包括查询的当前查询计划的相对成本(开销)。可以从Execute查询或Show History接口调用Show Plan。查询计划是在准备(编译)查询时生成的; 当编写查询并选择Show Plan按钮时,就会发生这种情况。不必执行查询来显示其查询计划。Show Plan在为无效查询调用时显示`SQLCODE`和错误消息。 ## SQL语句的结果 在“执行查询”文本框中编写SQL代码之后,可以通过单击“执行”按钮来执行代码。这要么成功执行SQL语句并在代码窗口下面显示结果,要么SQL代码失败。如果SQL代码失败,它会在code窗口下面显示一条错误消息(红色); 按下Show Plan按钮将显示`SQLCODE`错误和错误消息。 执行查询SQL代码执行作为后台进程执行。在执行代码时,Execute按钮被Cancel按钮替换。这允许取消长时间运行的查询的执行。 ### 查询数据显示 如果选中了行号框,结果集将作为表返回,行计数器将显示为第一列(`#`)。 其余的列将按照指定的顺序显示。RowID (ID字段)可以显示或隐藏。每个列都由列名(如果指定了,也可以是列别名)标识。聚合、表达式、子查询、主机变量或文字选择项可以由列别名(如果指定)标识,或者由单词`Aggregate_`、`Expression_`、`Subquery_`、`HostVar_`或`Literal_`后跟选择项序列号(默认情况下)标识。 如果行列不包含数据(`NULL`),结果集将显示一个空白的表格单元格。 指定一个空字符串文本将显示一个`HostVar_`字段,其中包含一个空白的表格单元格。 指定`NULL`显示一个带有空白单元格的`Literal_`字段。 如果选择的字段是日期、时间、时间戳或%List编码的字段,则显示的值取决于显示模式。 以下显示特性是管理门户SQL接口独有的,执行查询结果显示和打开表数据显示: - 数据类型`%Stream.Globalcharacter`的流字段将实际数据(最多100个字符)作为字符串显示。如果流字段中的数据长于100个字符,则显示数据的前100个字符,后跟省略的省略号(`...`)。 - 数据类型`%Stream.GlobalBinary`作为的流字段。 - 字符串数据字段根据需要,以完整的方式显示实际数据。 - Integer字段在结果表单元格中右对齐。 `ROWID`,`NUMERIC`和所有其他字段都是左对齐的。 当使用动态SQL代码,SQL Shell或嵌入式SQL代码执行相同的查询时,不会发生这些结果显示功能。 如果指定的查询返回多个结果集,则执行查询将这些结果集显示为命名选项卡:`Result #1`, `Result #2`等。 ### 查询执行指标 如果成功,则执行查询显示性能信息和缓存查询例程的名称。如果显示数据以显示,则显示在性能信息下方。执行信息包括行计数,性能,缓存查询,显示缓存的查询名称,最后更新指定查询的最后一次执行的时间戳。 - Row count:对于`CREATE TABLE`这样的DDL语句,如果操作成功,则显示`Row count: 0`。 对于`INSERT`、`UPDATE`或`DELETE`等DML语句,显示受影响的行数。 对于`TRUNCATE TABLE`语句,快速`TRUNCATE`操作不能确定实际删除的行数,而是设置行数:-1。 对于`SELECT`,显示作为结果集返回的行数。注意,返回的行数由Max设置控制,它可能低于可以选择的行数。 对于多个结果集,列出每个结果集的行数,用/字符分隔。 指定一个或多个聚合函数(且没有选择字段)的查询总是显示`Row count: 1`,并返回表达式、子查询和聚合函数的结果,即使`FROM`子句表不包含行。 一个不指定聚合函数和不选择行的查询总是显示`Row count: 0`并且不返回结果,即使该查询只指定不引用`FROM`子句表的表达式和子查询。 带`no FROM`子句的查询总是显示`行数:1`,并返回表达式、子查询和聚合函数的结果。 - 性能:以运行时间(以秒为单位)、全局引用总数、执行的命令总数和磁盘读取延迟(以毫秒为单位)来衡量。 如果该查询存在缓存的查询,那么这些性能指标将用于执行缓存的查询。 因此,查询的第一次执行将比后续执行具有更高的性能指标。 如果指定的查询返回多个结果集,那么这些性能指标就是所有查询的总和。 要更深入地分析这些性能指标,可以运行`MONLBL`(逐行监视实用程序)并使用星号通配符`%sqlcq*`指定例程名称。 请参考使用`^%SYS.MONLBL`检查例程性能。 - 缓存查询:自动生成的缓存查询类名。 例如,`%sqlcq.USER.cls2`表示用户名称空间中的第二个缓存查询。 每个新的查询被分配一个新的缓存的查询名称,该名称具有下一个连续的整数。 通过单击此缓存查询名称,以显示关于缓存查询的信息,以及显示其显示计划或执行缓存查询的进一步链接。 关闭管理门户或停止InterSystems IRIS不会删除缓存的查询或重置缓存的查询编号。 要从当前命名空间中清除缓存的查询,请调用%`SYSTEM.SQL.Purge()`方法。 并不是所有的SQL语句都会导致缓存的查询。与现有缓存查询相同的查询,除了文字替换值(例如`TOP`子句值和谓词文字)之外,不会创建新的缓存查询。有些SQL语句是不缓存的,包括DDL语句和权限分配语句。 非查询SQL语句,如`CREATE TABLE`,也会显示缓存的查询名。 然而,这个缓存的查询名称被创建然后立即删除; 下一个SQL语句(查询或非查询)重用相同的缓存查询名称。 - 最后一次更新:最后一次执行查询(或其他SQL操作)的日期和时间。 这个时间戳在每次执行查询时都被重置,即使在重复执行相同的查询时也是如此。 - 成功执行还提供了一个打印链接显示打印查询窗口,它给你选择打印或导出到一个文件中查询文本和/或查询的结果集。点击查询和结果切换使可以显示或隐藏文本或查询结果集的查询,查询结果集显示包含名称空间的名字,结果集的数据行数,一个时间戳,缓存的查询名称。 (注意,时间戳是调用Print查询窗口的时间,而不是执行查询的时间。) “打印查询”按钮用于打印查询窗口的屏幕截图。 “导出到文件”复选框显示指定导出文件格式(`xml、hdml、pdf、txt、csv`)和导出文件路径名的选项。 Export选项忽略查询和结果切换,并始终只导出结果集数据(默认为`:exportQuery.pdf`)和行数(默认为`:exportQueryMessages.pdf`); 不包括查询文本、名称空间、时间戳和缓存的查询名称。 如果不成功,则Execute Query显示错误消息。 可以单击Show Plan按钮来显示相应的`SQLCODE`错误值和消息。 ## 显示历史 单击“显示历史记录”可列出当前会话期间执行的SQL语句。 Show History列出从该接口调用的所有SQL语句,包括那些成功执行和那些执行失败的语句。 默认情况下,SQL语句按执行时间列出,最近执行的语句出现在列表的顶部。可以单击任何列标题,根据列值按升序或降序排列SQL语句。从Show History列表中执行SQL语句将更新其执行时间(本地日期和时间戳),并增加其计数(执行次数)。 可以过滤Show History列表,如下所示:在过滤框中指定一个字符串,然后按Tab键。只有包含该字符串的历史项才会包含在刷新后的列表中。 筛选器字符串可以是在SQL语句列中找到的字符串(比如表名),也可以是在执行时间列中找到的字符串(比如日期)。 过滤字符串不区分大小写。 在显式地更改过滤器字符串之前,它将一直有效。 通过选择语句,可以在“Show History”中修改和执行SQL语句,该语句将显示在“execute Query”文本框中。 在“执行查询”中,可以修改SQL代码,然后单击“执行”。 对从Show History中检索到的SQL语句进行任何更改,都会将其作为新语句存储在Show History中; 这包括不影响执行的更改,如更改字母大小写、空格或注释。 空格不会显示在Show History中,但是当从Show History中检索SQL语句时,会保留空格。 通过单击Show History列表中SQL语句右侧的execute按钮,可以直接从Show History列表中执行(重新运行)未修改的SQL语句。 注意,Show History列表与缓存查询列表不同。 Show History列出当前会话中调用的所有SQL语句,包括那些在执行过程中失败的语句。 ## 其他SQL接口 InterSystems IRIS支持许多其他编写和执行SQL代码的方法,在本手册的其他章节中有描述。 这些包括: - 嵌入式SQL:嵌入ObjectScript代码中的SQL代码。 - 动态SQL:使用%SQL。 语句类方法(或其他结果集类方法)用于从ObjectScript代码中执行SQL语句。 - SQL Shell:在终端使用SQL Shell接口执行动态SQL。
文章
Hao Ma · 一月 15, 2021

npm-iris概览

什么是npm-iris? NPM是“No Project Mess(项目不乱)”的缩写。 NPM是使用Intersystems IRIS和Bootstrp 4建成的项目和任务管理应用程序。 NPM的创建初衷是通过一个简单直观的项目和任务管理软件,帮助开发者和小型商业公司降低日常问题的复杂度。 它能提供不同的任务视图,包括电子表格、看板、日历,甚至甘特图! 为什么? 在不同的团队中工作,您会发现不同的人喜欢不同的工具。 所以,有时您会在一个项目中使用甘特图,在另一个项目中使用看板,在其他项目中使用纸上的列表…… NPM专注于任务。无论您和您的团队喜欢以哪种方式查看。只需单击并更改您的视图。 功能 初始安装 项目 用户 任务 - 创建和管理任务 调度程序 - 任务的日历视图 看板 - 用看板风格管理您的任务 甘特图 - 使用甘特图查看截止日期、里程碑和进度 新特性/改进的路线图 OAuth2身份验证 项目/团队/用户的安全性 时间跟踪 自定义日历(假期) 支持附件 利用AppS.REST框架 Vue.js版本 Home面板,可以查看活动的概况 试一下这款应用程序! http://npm-iris.eastus.cloudapp.azure.com:52773/npm/home.csp 如果您喜欢这个应用程序,并认为我值得您的投票,请投票给npm-iris! https://openexchange.intersystems.com/contest/current
文章
Louis Lu · 一月 7, 2021

FAQ 常见问题系列--RHEL V7.2 上的 Caché 进程故障

**RHEL V7.2 上的 Caché 进程故障** InterSystems WRC 处理了几个有关进程错误引发的问题,这些问题可以归因于 Red Hat Linux 最近的一次更新。 RHEL V7.2 (systemd-219-19.el7.x86_64) 中实现的一个新功能可能导致操作系统 IPC(进程间通信)信号量在 非系统用户注销时被解除分配(系统用户,即 UID 编号小于 1000 的用户除外)。 Caché 在内部利用 IPC 信号量来控制 Caché 进程的运行(例如,当尝试唤醒 Caché 进程时)。 这通过“semop”系统服务来实现,如果操作系统意外删除了 Caché 用于进行 IPC 通讯的信号量,则进程可能会出现错误。 如果发生这种情况,在 cconsole.log 中会找到以下证据: “System error while trying to wake-up a process, code = 22”(尝试唤醒进程时系统出错,代码 = 22) 以及在 Caché SYSLOG 中也会记录相应的错误,例如以下典型示例: Err   Process    Date/Time           Mod Line  Routine            Namespace 22    39761      09/29/2016 04:41:27PM 61  359   BF0+1359^Ens.Queue.1 HSBUS 这最终可能导致 Caché 的运行实例处于挂起状态。 以下是 Redhat 提供的一篇文章的链接,文中给出了有关此功能的详细信息以及禁用该功能的方法: [https://access.redhat.com/solutions/2062273](https://access.redhat.com/solutions/2062273 "Follow link")   此问题已在 systemd-219-19.el7_2.4(通过 RHBA-2016-0199 发布 ()中修复。
问题
water huang · 四月 17, 2021

ensemble 2016 如何快速的调用dll文件。

如图 dll放在 我调用的方式如下 期待能够在ensemble里面能便捷的调用dll,各种语言开发的dll,至少能支持c#生成的dll, 在Ensemble 2016中,使用$ZF(-4)来操作DLL是Caché的Callout网关的底层实现之一。这种方式比较通用。当然,如果这些DLL(ActiveX/COM)注册在Ensemble服务器上(Windows服务器),还有别的调用方式:使用Caché Activate 网关,用Studio来产生这些DLL的代理类,然后您就可以像使用Ensemble/Caché类一样使用这些DLL里的方法了。 使用Caché Activate 网关 这个并不好用。服务器重启后 需要重启网关,还很可能需要重新导入dll来生成代理类。因此这样的方式 我已经弃用,或者说 “可能需要重新导入dll来生成代理类” 这个是我操作不对才导致这样的结果?使用$ZF(-4)来操作DLL,这个dll具有一些特殊要求?比如? 如果dll重新编译过,那么是需要重新生成代理类的;其它情况下并不需要。另外,Ensemble 2016里有.net 网关,通过Studio来建立dll代理类。不过它依然需要在dll代码发生变化时重新生成代理类。 这也是后续版本(尤其是InterSystems IRIS)推出动态对象网关的原因:通过动态网关就不用生成代理类了,从而避免因为.net/java端发生代码变更而需要重新生成代理类。$ZF()对DLL没有特殊要求。
文章
Lele Yang · 一月 30, 2022

FAQ 常见问题系列 -- 系统管理篇 Linux OOM Killer问题

Linux内核机制OOM Killer,也即Out of Memory Killer, 顾名思义,该机制的主要职能就是当内存不足时,选择并杀掉一些进程,以使系统继续运行。 Caché/Ensemble/IRIS的多个客户曾经遇到过与此相关的系统宕机,宕机的直接原因是数据库核心写进程Write Daemon被OOM Killer选中并杀掉了,在我们的日志文件中可以看到如下信息, 06/15/21-10:50:31:035 (13579) 3 Daemon WRTDMN (pid 13588) died. Freezing system 06/15/21-10:52:25:940 (13601) 2 System Process 'WRTDMN' terminated abnormally (pid 13588) 与之对应,在操作系统的日志文件中可以看到如下记录, Jun 15 10:50:34 localhost kernel: Free swap = 0kB Jun 15 10:50:34 localhost kernel: Total swap = 20479996kB Jun 15 10:50:34 localhost kernel: 16777102 pages RAM Jun 15 10:50:34 localhost kernel: 0 pages HighMem/MovableOnly Jun 15 10:50:34 localhost kernel: 324506 pages reserved Jun 15 10:50:30 localhost kernel: cache invoked oom-killer: gfp_mask=0x42d0, order=3, oom_score_adj=0 Jun 15 10:50:35 localhost kernel: Out of memory: Kill process 13588 (cache) score 127 or sacrifice child InterSystems在后续的IRIS版本中(从IRIS2021.1.0开始)已经对此做了优化,以使Write Daemon不那么容易被OOM Killer选中。但是要从根本上解决该问题,还是应当重新审视系统的内存分配,如Huge Page,共享内存等,检查Linux内存相关参数,如vm.swappiness,vm.dirty_background_ratio,vm.dirty_ratio等,以使系统可以在内存使用方面达到最大的效用。
公告
Claire Zheng · 一月 25, 2022

恭喜Louis喜获重磅证书——HL7 FHIR R4 Proficiency Exam

亲爱的开发者们, 很高兴同大家分享一个好消息!我们中文社区版主、InterSystems高级销售工程师Louis(@Louis Lu)于近日顺利通过“HL7 FHIR R4 Proficiency Exam”并取得资格认证证书! HL7 FHIR(R4)能力证书可以证明在最新和最热门的HL7标准方面达到行业公认的专业水平。考试涵盖了以下内容:FHIR原则;FHIR资源的基本概念;交换机制;一致性和实施指导;如何使用术语;如何建立安全和可靠的FHIR解决方案;FHIR维护过程;以及如何使用和处理FHIR许可和知识产权(IP)。 FHIR®(快速医疗互操作性资源)是HL7的下一代标准框架,它建立并结合了HL7第二版(V2)、第三版(V3)和临床文档架构(CDA®)产品线的最佳功能,同时利用了最新的网络标准并注重于实际实施的能力。FHIR适合在各种情况下使用,如手机应用程序、云通信、基于电子健康记录(EHR)的数据共享、大型医疗机构间服务器通信等等。FHIR还可以支持使用一个标准涵盖尽可能多的应用场景,实现医疗信息化真正意义的互操作性,是智慧医院数字化转型,实现组装式应用创新的重要基础。 一起来恭喜Louis(@Louis Lu)吧✿✿ヽ(°▽°)ノ✿✿✿ヽ(°▽°)ノ✿(*^▽^*) 恭喜🎉🎉
文章
Michael Lei · 三月 10, 2023

如何使用最新的 IRIS Native SDK for Python 用 Python 遍历 IRIS Global数据结构

InterSystems IRIS 2022.2 具有适用于 Python 的原生 SDK (https://docs.intersystems.com/iris20222/csp/docbook/Doc.View.cls?KEY=PAGE_python_native)。 我们知道如何使用 IRIS Object Script $Order 函数遍历Global数据结构。 SET key= "" FOR { SET key= $ORDER ( ^myglobal (key)) QUIT :key= "" WRITE !, ^myglobal (key) } 如何使用 IRIS Native SDK 从 Python 执行相同的操作?这里有一个代码示例: import iris args = { 'hostname' : '127.0.0.1' , 'port' : 51772 , 'namespace' : 'USER' , 'username' : '_SYSTEM' , 'password' : 'SYS' } conn = iris.connect(**args) # Create an iris object irispy = iris.createIRIS(conn) # Create a global array in the USER namespace on the server irispy.set( 'A' , 'root' , 'foo' , 'SubFoo' ) irispy.set( 123 , 'root' , 'bar' , 'lowbar' , 'UnderBar' ) irispy.set( 124 , 'root' , 'bar' , 'lowbar' , 'UnderBar2' ) irispy.set( "hi" , 'root' , 'bar' , 'lowbar' ) irispy.set( "hi again" , 'root' , 'bar3' ) # Read the values from the database and print them subfoo_value = irispy.get( 'root' , 'foo' , 'SubFoo' ) underbar_value = irispy.get( 'root' , 'bar' , 'lowbar' , 'UnderBar' ) underbar2_value = irispy.get( 'root' , 'bar' , 'lowbar' , 'UnderBar2' ) lowbar_value = irispy.get( 'root' , 'bar' , 'lowbar' ) bar3_value = irispy.get( 'root' , 'bar3' ) print( 'Created two values: ' ) print( ' root("foo","SubFoo")=' , subfoo_value) print( ' root("bar","lowbar","UnderBar")=' , underbar_value) print( ' root("bar","lowbar","UnderBar2")=' , underbar2_value) print( ' root("bar","lowbar")=' , lowbar_value) print( ' root("bar3")=' , bar3_value) direction = 0 # direction of iteration (boolean forward/reverse) next_sub = chr( 0 ) # start at first possible subscript subs = [] print( "\n Iterating root \n" ) isDef = irispy.isDefined( 'root' , *subs) while isDef: next_sub = irispy.nextSubscript( False , 'root' , *subs, next_sub) # get first subscript if next_sub == None : # we finished iterating nodes on this tree branch, move a level up if len(subs) == 0 : # no more things to iterate break next_sub = subs.pop( -1 ) # pop last subscript in order to continue iterating this level if irispy.isDefined( 'root' , *subs, next_sub) == 11 : print( 'root(' ,*subs, next_sub, ')=' ,irispy.get( 'root' , *subs, next_sub)) continue continue isDef = irispy.isDefined( 'root' , *subs, next_sub) if isDef in [ 10 , 11 ]: # keep building subscripts for depth first search subs.append(next_sub) next_sub = chr( 0 ) continue elif isDef == 1 : # reached a leaf node, print it print( 'root(' ,*subs, next_sub, ')=' ,irispy.get( 'root' , *subs, next_sub)) else : # def 0 is not really expected print( "error" ) irispy.kill( 'root' ) conn.close() exit( -1 ) # Delete the global array and terminate irispy.kill( 'root' ) # delete global array root conn.close()
文章
Claire Zheng · 九月 9, 2021

优秀案例:吉大中日联谊医院“通关”互联互通五级乙等

在医院信息化领域,中日联谊医院最近一次站在行业瞩目的聚光灯下,是在2021年7月。在国家卫生健康委统计信息中心发布的《关于2020年度国家医疗健康信息互联互通标准化成熟度测评结果公示的通知》中,9家医院获评五级乙等,中日联谊医院名列其中。这也是目前为数不多的“通关”互联互通五乙的医院之一。2021年是《国家医疗健康信息医院信息互联互通标准化成熟度测评方案(2020年版)》(以下简称新版测评方案)施行的第一个年头。由于测评方案的细化、参评机构的数量增多,业界普遍反映医院互联互通测评的整体难度正在逐年增大。而五级乙等,已是医疗机构目前所能取得的最高级别。 在互联互通新版测评方案中,对互联互通功能的“实际落地”与“有效应用”提出了很高的要求。在五级乙等的分级要求中就明确提出:“实现公众服务应用功能数量不少于27个、医疗服务应用功能数量不少于30个;提供较为完善的互联网诊疗服务,初步实现基于平台的临床决策支持、闭环管理、大数据应用。” 医院信息化建设立足于实际应用,为医院的医疗服务与运营管理提供助力,这是中日联谊医院能够获评五级乙等的重要原因之一。 医院在参与测评的过程中,遇到的首要问题即异构系统的接入问题。互联互通新版测评方案对医院信息系统内外联通业务的数量提出了明确要求,其中对五级乙等的分级要求是:集成平台至少需要接入54个内部业务系统,以及不少于7个外部机构数量,实现基于平台的内部与外部联通业务。 为达到上述要求,医疗机构需有效解决异构系统间的数据交互问题,完成交互服务接口和闭环管理改造。中日联谊医院采用了“东华医为医院信息平台产品”,该产品依托InterSystems技术实现,是互联互通标准化成熟度测评工作的基础。InterSystems数据平台技术不仅稳定可靠,有效支撑数百万级的大规模消息吞吐交换,而且以其强大的可扩展性、易用性和互操作能力,使各异构系统的直接连接更简单,降低了交互服务接口开发的时间和成本,帮助医院高质、高效地推进了业务联通工作。 点击此次,阅读全文
文章
Michael Lei · 六月 6, 2023

2023 年全球峰会初体验

大家好! 我相信很多人都希望出席 2023 年全球峰会,但出于某种原因无法出席。以下是对 6 月 4 日和 5 日发生的事情的简要回顾。 尽管正式的开幕式要到周日晚上才会举行,但峰会前的活动还是很精彩的。亮点之一(特别是对于这里的体育爱好者而言)是早上的高尔夫锦标赛和足球(又名足球)比赛。不能说关于足球的任何事情,因为我不在场(如果你在场,请在评论部分发表评论和照片!),但据我所知,这是一场有趣的比赛。我可以告诉你关于高尔夫的事! 比赛从早上 6 点开始,一直持续到下午 2 点左右。一开始天气阴沉,雨刚下完。但几个小时后,太阳出现了,防晒霜也随之出现。让我告诉你,50SPF 感觉不够! 为了让它更有趣,当地的动物群决定也出去玩。 在宣布获奖者并享用午餐后,我们返回 The Diplomat Beach Hotel 参加其他活动。 例如,下午有一场女性活动。 这导致周日的主要活动 - 欢迎酒会!这是看到熟悉的面孔并与同事和朋友取得联系的最佳时机。 例如,英语社区的版主(@Muhammad.Waseem、@Dmitry.Maslennikov、@Irène.Mykhailova): 和法语社区(@Lorenzo.Scalese、@Irène.Mykhailova、@Dmitry.Maslennikov、@Guillaume.Rongier7183): 这是“准备”日。主要内容从周一开始! Terry Ragon 开启了峰会,在他的演讲中提醒大家任何成功的公司都必须创新才能保持相关性。 InterSystems 就是这样的公司之一! 此外,他祝贺大家 InterSystems 成立 45 周年和第 30 届全球峰会!这不是令人兴奋吗?不知道你怎么想,公司成立的时候我还没有出生呢! 开场白之后,第一个主题演讲是关于医疗保健的。其中一点 @Donald.Woodlock 谈到了AI 以及它如何拉近开发人员与客户的距离,而不是相反。 在主题演讲(和午餐)之后,每个人都分散到不同的会议、演讲、会议等。我回到了 Tech Exchange 的开发者社区展位。 如果你在峰会上,别忘了顺路过来——我很乐意给你一些礼物作为简单行动的回报 😘 如果你认识一些还不是社区成员的人,鼓励他们过来也得到一些赃物。此外,请查看全球大师赛- 峰会期间可兑换一些奖励: 还有一些新的(和旧的最爱)奖励!有传言说,我们甚至很快就会有笔记本电脑贴纸! 无论如何,在 DevCom 展位让我有机会与新朋友交谈,并结识其他有空的版主。 @Guillaume.Rongier7183 和@Dmitry.Maslennikov @Lorenzo.Scalese、@Dmitry.Maslennikov 和@Francisco.López1549 如果您对背景中的演示文稿感兴趣,请看这里。 此外,参加 Tech Exchange 意味着我可以关注那里正在进行的所有演示。例如,了解容器 😉 在所有这些兴奋之后,我们都去吃晚餐和演示。 玩游戏,玩得很开心。 这是 2023 年全球峰会的第一个官方日。敬请期待接下来的活动!
文章
Hao Ma · 一月 30, 2021

WebGateway系列(2): 配置Apache连接IRIS

## 检查Apache工作状态 确认Apache正常工作, apache的版本已经安装路径。 [root@centos7 ~]# httpd -v Server version: Apache/2.4.6 (CentOS) Server built: Apr 24 2019 13:45:48 [root@centos7 ~]# systemctl status httpd ● httpd.service - The Apache HTTP Server Loaded: loaded (/usr/lib/systemd/system/httpd.service; enabled; vendor preset: disabled) Active: active (running) since Mon 2020-06-15 16:46:36 CST; 5min ago Docs: man:httpd(8) man:apachectl(8) Main PID: 6506 (httpd) Status: "Total requests: 0; Current requests/sec: 0; Current traffic: 0 B/sec" Tasks: 272 Memory: 31.3M CGroup: /system.slice/httpd.service ├─6506 /usr/sbin/httpd -DFOREGROUND ├─6592 /usr/sbin/httpd -DFOREGROUND ├─6607 /usr/sbin/httpd -DFOREGROUND ├─6608 /usr/sbin/httpd -DFOREGROUND ├─6609 /usr/sbin/httpd -DFOREGROUND ├─6610 /usr/sbin/httpd -DFOREGROUND ├─6611 /usr/sbin/httpd -DFOREGROUND ├─6612 /usr/sbin/httpd -DFOREGROUND ├─6613 /usr/sbin/httpd -DFOREGROUND ├─6622 /usr/sbin/httpd -DFOREGROUND ├─6623 /usr/sbin/httpd -DFOREGROUND └─6633 /usr/sbin/httpd -DFOREGROUND Jun 15 16:46:36 centos7 systemd[1]: Starting The Apache HTTP Server... Jun 15 16:46:36 centos7 systemd[1]: Started The Apache HTTP Server. [root@centos7 ~]# 确认httpd.conf的位置。 在CentOS7中此位置为/etc/httpd/conf, 其他linux系统可能有其他位置, 如果不确认,可以使用 find命令寻找. [root@centos7 ~]# ll /etc/httpd/conf total 56 -rw-r--r-- 1 root root 890 Jun 26 2019 healthshare.conf -rw-r--r-- 1 root root 0 Jun 26 2019 healthshare.conf_save -rw-r--r-- 1 root root 11786 Jun 30 2019 httpd.conf -rw-r--r-- 1 root root 11753 Jun 26 2019 httpd.conf.bak -rw-r--r-- 1 root root 11746 Jun 30 2019 httpd.conf2 -rw-r--r-- 1 root root 13077 Apr 24 2019 magic [root@centos7 ~]# 从Caché所在服务器用浏览器检查Apache测试页面可以访问。如果在Apache本地服务器访问, 网址为127.0.0.1(如果远端无法访问,请首先检查防火墙,后面步骤中有介绍) picture testing123 ## 关闭SELinux配置 查询确认SELinux状态为disabled [root@centos7 ~]# getenforce Disabled 如果非disabled状态,需要修改配置文件实现, 下图为修改后的文件内容,修改后重启电脑生效。 [root@centos7 ~]# cat /etc/selinux/config # This file controls the state of SELinux on the system. # SELINUX= can take one of these three values: # enforcing - SELinux security policy is enforced. # permissive - SELinux prints warnings instead of enforcing. # disabled - No SELinux policy is loaded. SELINUX=disabled # SELINUXTYPE= can take one of three two values: # targeted - Targeted processes are protected, # minimum - Modification of targeted policy. Only selected processes are protected. # mls - Multi Level Security protection. SELINUXTYPE=targeted [root@centos7 ~]# ## 检查防火墙 确认apache所在服务器的防火墙打开了80端口。(为简化步骤, 这里不讨论Web Server的SSL接入) [root@centos7 ~]# systemctl status firewalld ● firewalld.service - firewalld - dynamic firewall daemon Loaded: loaded (/usr/lib/systemd/system/firewalld.service; disabled; vendor preset: enabled) Active: active (running) since Mon 2020-06-15 17:24:15 CST; 2s ago Docs: man:firewalld(1) Main PID: 27433 (firewalld) Tasks: 2 Memory: 25.1M CGroup: /system.slice/firewalld.service └─27433 /usr/bin/python -Es /usr/sbin/firewalld --nofork --nopid Jun 15 17:24:15 centos7 systemd[1]: Starting firewalld - dynamic firewall daemon... Jun 15 17:24:15 centos7 systemd[1]: Started firewalld - dynamic firewall daemon. [root@centos7 ~]# firewall-cmd --state running [root@centos7 ~]# firewall-cmd --zone=public --list-ports [root@centos7 ~]# firewall-cmd --zone=public --add-port=80/tcp --permanent Success [root@centos7 ~]# firewall-cmd --reload success [root@centos7 ~]# firewall-cmd --zone=public --list-ports 80/tcp [root@centos7 ~] 如果Caché安装在另一台服务器, Web gateway和Caché间的通信通过Caché的superserver端口(默认1972), 因此Caché所在服务器的防火墙必须运行此端口访问。 ## 对Apache调优 如果apache的工作模式为Prefork, 通过修改配置文件后重启服务,将工作模式改成“worker”(下面cat命令显示修改后的配置文件) [root@centos7 ~]# apachectl -V | grep MPM Server MPM: prefork [root@centos7 ~]# vim /etc/httpd/conf.modules.d/ [root@centos7 ~]# cat /etc/httpd/conf.modules.d/00-mpm.conf # Select the MPM module which should be used by uncommenting exactly # one of the following LoadModule lines: # prefork MPM: Implements a non-threaded, pre-forking web server # See: http://httpd.apache.org/docs/2.4/mod/prefork.html #LoadModule mpm_prefork_module modules/mod_mpm_prefork.so # worker MPM: Multi-Processing Module implementing a hybrid # multi-threaded multi-process web server # See: http://httpd.apache.org/docs/2.4/mod/worker.html # LoadModule mpm_worker_module modules/mod_mpm_worker.so # Worker MPM parameters ServerLimit 40 StartServers 10 MaxRequestWorkers 1000 MinSpareThreads 75 MaxSpareThreads 250 ThreadsPerChild 25 # event MPM: A variant of the worker MPM with the goal of consuming # threads only for connections with active processing # See: http://httpd.apache.org/docs/2.4/mod/event.html # #LoadModule mpm_event_module modules/mod_mpm_event.so [root@centos7 ~]# systemctl restart httpd [root@centos7 ~]# apachectl -V | grep MPM Server MPM: worker [root@centos7 ~]# ## 安装Web Gateway 最新的IRIS或者HealthConnect安装包可能不包含让用户选择是否安装csp/web gateway的选项, 因此大多数情况, 用户更多的是使用专门的Web/CSP gateway的安装包来安装, 无论Apach Server 和Caché/IRIS Server是否在同一台服务器上。 以下的介绍是用WebGateway 2020.1版本安装的过程。 1. 解压缩安装包到一个临时文件夹 [root@centos7 ~]# tar -xzf WebGateway-2020.1.0.197.0-lnxrhx64.tar.gz 2. 使用touch命令在/etc/httpd/conf.d目录下创建空配置文件isc.conf Apaceh启动时会调用主配置文件/etc/httpd/conf/httpd.conf。 该文件的默认配置项中会自动include目录/etc/httpd/conf.d下的*.conf文件, 因此不同的应用创建不同的conf文件放在conf.d目录下是方便管理的通常做法。 这个.conf的文件名可以任意名字,isc.conf只是示意。(下一步安装Web Gateway时需要输入此名字)。 [root@centos7 httpd]# touch /etc/httpd/conf.d/isc.conf 同理手动 在 /opt/webgateway/bin 下面建立CSP.ini文件,并且赋予读写权限 3. 到解压后的安装包目录下的install子目录, 执行以下命令: [root@centos7 ~]# cd WebGateway-2020.1.0.197.0-lnxrhx64/ [root@centos7 WebGateway-2020.1.0.197.0-lnxrhx64]# ls install lnxrhx64 [root@centos7 WebGateway-2020.1.0.197.0-lnxrhx64]# cd install/ [root@centos7 install]# ./GatewayInstall Starting Web Gateway installation procedure. Please select WebServer type. Choose "None" if you want to configure your WebServer manually. 1) Apache 2) None WebServer type? [2] 1 Please enter location of Apache configuration file [/etc/httpd/conf/httpd.conf]: /etc/httpd/conf.d/isc.conf Enter user name used by Apache server to run its worker processes : Please enter location of Apache executable file : Apache version 2.4 is detected. Please enter destination directory for Web Gateway files [/opt/webgateway]: Do you want to create directory /opt/webgateway [Y]: Please enter hostname of your InterSystems IRIS server [localhost]: HCDEMO Please enter superserver port number for your InterSystems IRIS server [51773]: Please enter InterSystems IRIS configuration name [IRIS]: HCDEMO (注 这里的 configuration name 其实是csp.ini 中服务器的配置代称,可以任意起,不一定必填为服务器本身的hostname) Please enter directory for static CSP content [/opt/webgateway/hcdemo]: Do you want to create directory /opt/webgateway/hcdemo [Y]: Installing InterSystems IRIS Web Gateway for Apache: ------------------------------------------------------------------ Apache configuration file: /etc/httpd/conf.d/isc.conf InterSystems IRIS configuration name: HCDEMO InterSystems IRIS server address: HCDEMO InterSystems IRIS server port number: 51773 Web Gateway installation directory: /opt/webgateway ------------------------------------------------------------------ Do you want to continue and perform the installation [Y]: Updating Apache configuration file ... - /etc/httpd/conf.d/isc.conf * You need to restart your Apache server before any configuration changes will take effect. Web Gateway configuration completed! [root@centos7 install]# 安装结束后 - 检查安装目录被生成,并包含CSPGateway文件 - 检查isc.conf文件,确认文件已经被写入配置信息。 - 登录CSP Gateway管理页面查看: http://WebServer:80/csp/bin/Systems/Module.cxw 如果不是在Apache服务器访问而是远程登录该页面,此时会出现错误提示,显示CSP Gateway的版本信息和“You are not authorized to use this facility”的提醒。这是CSP Gateway的安全策略。默认不允许远程的访问,对于需要远程访问的源IP地址或者源网段,用户必须手工在CSP.ini配置文件的[SYSTEM]块里添加,比如添加 ”System_Manager=172.16.58.100",或者"System_Manger=172.16.*.*"。虽然不推荐,但"System_Manager=*.*.*.*”允许任意地址远程访问的远程访问。如果CSP.ini没有自动生成,那需要手动 在 /opt/webgateway/bin 下面建立此文件,并且赋予读写权限。 下面是添加System_Manager后的CSP.ini例子: [root@centos7 bin]# cat /opt/webgateway/bin/CSP.ini [SYSTEM_INDEX] HCDEMO=Enabled LOCAL=Enabled [HCDEMO] Ip_Address=HCDEMO TCP_Port=51773 Minimum_Server_Connections=3 Maximum_Session_Connections=6 [APP_PATH_INDEX] /=Enabled /csp=Enabled /hcdemo=Enabled [APP_PATH:/] Default_Server=HCDEMO Alternative_Server_0=1~~~~~~HCDEMO [APP_PATH:/csp] Default_Server=HCDEMO Alternative_Server_0=1~~~~~~HCDEMO [APP_PATH:/hcdemo] Default_Server=HCDEMO Alternative_Server_0=1~~~~~~HCDEMO [SYSTEM] SM_Timeout=28800 Server_Response_Timeout=60 No_Activity_Timeout=86400 Queued_Request_Timeout=60 Configuration_Initialized=Tue Nov 17 07:58:29 2020 Configuration_Initialized_Build=2001.1740 System_Manager=*.*.*.* [LOCAL] Ip_Address=127.0.0.1 TCP_Port=1972 Minimum_Server_Connections=3 Maximum_Session_Connections=6 [root@centos7 bin]# ## 登录Web Gateway管理页面的抓图 检查Web Gateway的配置文件位置,版本,log位置 ## 配置CSP Gateway到IRIS的连接,并测试从Apache登录IRIS维护界面 ### 在CSP Gateway配置页面,查看Server Access。 Server Access中会列出这本CSP Gateway连接的IRIS实例的列表。在上面的安装步骤中,当问到了“ Please enter hostname of your InterSystems IRIS server [localhost]: HCDEMO ”选择了HCDEMO, 这时这个列表中会显示有两个Server, localhost和HCDEMO. (localhost无法被删除,遗憾) 下面检查HCDEMO Server的配置 - 检查服务器地址为127.0.0.1 - 添加到Caché服务器的账号密码,默认为CSPSystem, SYS 如果IIS服务器+Web Gateway和Caché位于两个不同的服务器, 或者需要添加到另一Caché Server的连接, 需要添加Server, 如下图, 需要的配置: Caché服务器的IP,superserver端口号, CSPSystem用于的密码,服务器的类型(可选) **测试Caché Server连接成功** 双击左边菜单栏的"Test Server Connection", 确认结果中收到"Server connection test was successful: ...."的结果。 ## 访问IRIS维护主页 (可选) 从链接 http://WebServer/csp/sys/Utilhome.csp 访问IRIS维护主页System Management Portal应该可以成功了,但您会发现有部分网页内容(element)无法加载。这是因为在默认的安装中,isc.conf中CSP Gateway路径的配置的"CSPFileTypes csp cls zen cxw"中只将这4种类型的请求发送给CSP Gateway, 而被称为Static file的文件,比如.js, .css, .png等等类型的文件并没有被发送给CSP Gateway. 这是另外的一个安全机制,强制客户人工的配置是否需要从Web服务器访问IRIS维护主页。如果答案是NO, 那么访问IRIS维护页面就只能通过PWS,用IRIS服务器的52773的接口。 如果用户认为从Web服务器访问IRIS维护页面是必要的, 需要修改CSPFileTypes配置,比如修改成"CSPFileTypes *",作用是把任意类型的请求发送给IRIS。以下是安装并修改后的isc.conf文件示例。 [root@centos7 conf.d]# cat isc.conf #### BEGIN-ApacheCSP-SECTION #### LoadModule csp_module_sa "/opt/webgateway/bin/CSPa24.so" CSPModulePath "/opt/webgateway/bin/" CSPConfigPath "/opt/webgateway/bin/" Alias /csp/ "/opt/webgateway/hcdemo/csp/" SetHandler csp-handler-sa SetHandler csp-handler-sa CSPFileTypes * AllowOverride None Options MultiViews FollowSymLinks ExecCGI Require all granted Require all denied AllowOverride None Options None Require all granted Require all denied #### END-ApacheCSP-SECTION #### #### BEGIN-ApacheCSP-SECTION-HCDEMO #### Alias /hcdemo/csp/ "/opt/webgateway/hcdemo/csp/" #### END-ApacheCSP-SECTION-HCDEMO #### [root@centos7 conf.d]# 注意isc.conf修改后需要重启apache server [root@centos7 conf.d]# systemctl restart httpd [root@centos7 conf.d]# ## 访问IRIS上的其他Web Application IRIS上其他的Web Application需要经过配置才可以发送到IRIS Server。这些Web Application可能是一个访问HTTP, REST的URL, 或者是一个用户自己定义的SOAP,甚至可能是一个简单的CSP文件。要确保他们被发送给IRIS Server, 用户需要: 1. 配置Apache配置文件isc.conf, 保证请求被发送给了CSP Gateway。 可以通过CSP Gateway管理页面的HTTP Trace来确认。 2. 如果需要,配置CSP Gateway, 将请求发送给IRIS. ### 访问带文件后缀的应用 在isc.conf中的中定义的是Web Server中文件对象的地址,比如"/opt/webgateway/bin/"是CSP Gateway的.so文件的存放位置。 Alias是URL中资源地址,比如"/csp/"到定义的映射。他们在apache中注册一个有后缀的文件的发送路径, 这个配置使得访问"http://WebServer/csp/sys/Utilhome.csp"可以成功发送给CSP Gateway。 Alias /csp/ "/opt/webgateway/hcdemo/csp/" CSPFileTypes * AllowOverride None Options MultiViews FollowSymLinks ExecCGI Require all granted Require all denied 对于其他的Web Application, 比如如果需要将"http://WebServer/test/Hello.csp"成功发送给CSP Gateway, 需要添加以下配置,它把路径为”/test/"的URL发送给CSP Gateway处理。 Alias /test/ "/opt/webgateway/hcdemo/csp/" 测试连接一个SOAP服务,注意这个服务要在IRIS的Web Applicatin里配置正确,它至少可以从PWS用匿名用户访问。(关于Web Application的配置另行文档, 简单说, 要匿名访问, 要使用%Security_WebGateway的资源).测试结果: [root@centos7 conf.d]# curl http://172.16.58.100/test/test.webservice1.cls?soap_method=winter Winter is Coming... [root@centos7 conf.d]# ### 访问其他URL应用 对于 “http://172.16.58.100/api/mgmnt/v2/”这样的URL地址, 映射到CSP Gateway处理需要的配置是。下面的配置保证对"/api/"开头的,没有文件地址的URL的处理: SetHandler csp-handler-sa CSP on 请求的结果如下: [root@centos7 ~]# curl -X GET "http://172.16.58.100/api/mgmnt/v2/" [{"name":"%Api.IAM.v1","webApplications":"/api/iam","dispatchClass":"%Api.IAM.v1.disp","namespace":"%SYS","swaggerSpec":"/api/mgmnt/v2/%25SYS/%25Api.IAM.v1"},{"name":"%Api.Mgmnt.v2","webApplications":"/api/mgmnt","dispatchClass":"%Api.Mgmnt.v2.disp","namespace":"%SYS","swaggerSpec":"/api/mgmnt/v2/%25SYS/%25Api.Mgmnt.v2"},{"name":"PetStore","dispatchClass":"PetStore.disp","namespace":"DEMO","swaggerSpec":"/api/mgmnt/v2/DEMO/PetStore"}][root@centos7 ~]# 备注: 如果得到了{"msg":"错误 #8754: Unable to use namespace: USER."},或者403 forbidden, 需要在IRIS上给Web Application "/api/mgmnt"添加”%DB_USER"的权限;或者,也可以将应用的“安全设置”设成"密码",然后使用下面的命令查看: [root@centos7 conf.d]# curl -i -X GET http://172.16.58.100/api/mgmnt/v2/ -u "_system:SYS" HTTP/1.1 200 OK。。。(后面省略) [{"name":"%Api.IAM.v1","webApplications":"/api/iam","dispatchClass":"%Api.IAM.v1.disp","namespace":"%SYS","swaggerSpec":"/api/mgmnt/v2/%25SYS/%25Api.IAM.v1"},{"name":"%Api.Mgmnt.v2","webApplications":"/api/mgmnt","dispatchClass":"%Api.Mgmnt.v2.disp","namespace":"%SYS","swaggerSpec":"/api/mgmnt/v2/%25SYS/%25Api.Mgmnt.v2"},{"name":"PetStore","dispatchClass":"PetStore.disp","namespace":"DEMO","swaggerSpec":"/api/mgmnt/v2/DEMO/PetStore"}][root@centos7 conf.d]# ### CSP Gateway配置 "Application Access" 通常情况下,CSP Gateway测试成功连接IRIS Server后,会发现IRIS上的Web Application列表,并添加到自己的”APPlicaiton Access"列表里。如下图所示。每次用户在IRIS添加一个新的Web应用, 只需要在isc.conf上做相应的配置,无需人工去更新CSP Gateway的配置。 特殊的情况,如果发现某个URL无法发送到IRIS。先打开了CSP Gateway的HTTP Trace,确认CSP Gateway可以收到请求消息但无法发送到IRIS, 这是需要人工检查并且配置"Application Access".
文章
Hao Ma · 三月 26, 2021

使用 IRIS 和 Python 创建聊天机器人

![图片](https://raw.githubusercontent.com/renatobanzai/iris-python-covid19/master/img/chatbot.gif) # 使用 IRIS 和 Python 创建聊天机器人 本文将展示如何把 InterSystems IRIS 数据库与 Python 集成,以服务于自然语言处理 (NLP) 的机器学习模型。 ### 为什么选择 Python? 随着在世界范围内的广泛采用和使用,Python 拥有了出色的社区,以及许多加速器 | 库用于部署任何类型的应用。 如果您感兴趣,请访问 https://www.python.org/about/apps/ ### Iris Globals 我接触到 ^globals 后很快就熟悉了,它们可以用作快速获取现成数据模型中数据的方法。 因此,首先,我将使用 ^globals 存储训练数据和对话以记录聊天机器人的行为。 ### 自然语言处理 自然语言处理或 NLP 是 AI 的一个主题,它创造了机器从我们的语言阅读、理解含义的能力。 显然,这并不简单,但是我将展示如何在这个广阔而美丽的领域中迈出您的第一步。 ### 演示 - 来试试吧 我在这里部署了 Chatbot 应用作为演示: [http://iris-python-suite.eastus.cloudapp.azure.com:8080](http://iris-python-suite.eastus.cloudapp.azure.com:8080) ### 工作原理 ### 机器学习 首先要知道与普通软件开发相比,机器学习具有不同的范式。 很难理解的要点是机器学习模型的开发周期。 **浅显解释预警** 一个标准的应用开发周期大概是这样: 开发代码 -> 测试(使用开发数据)-> 部署(真实用户数据) 机器学习代码本身不具有相同的价值。 它会与数据分担责任! 而且不是任意数据,是真实数据! 因为待执行的最终代码是由开发概念和所用数据合并生成。 所以机器学习应用周期类似于: 开发(训练)模型 + 真实数据 -> 验证 -> 部署此模型的结果 ### 如何训练模型? 训练模型的技术有很多,每种情况和目标都需要很大的学习曲线。 在本例中,我使用的是 [ChatterBot](https://github.com/gunthercox/ChatterBot) 库,该库封装了一些技术,并提供了训练方法和经过预处理的训练数据,有助于我们关注结果。 ### 预训练的模型语言和自定义模型 您可以由此开始拥有一个基本的会话聊天机器人。 您还可以创建所有数据来训练您的聊天机器人,全面满足您的需求,但这在短时间内很难完成。 在这个项目中,我使用 en_core_web_sm 作为对话的基础,并与可以通过[表单](http://iris-python-suite.eastus.cloudapp.azure.com/chatbot-training-data)创建的自定义训练数据合并 ### 基础架构 ![图片](https://raw.githubusercontent.com/renatobanzai/iris-python-covid19/master/img/chatbot_diagram.png) ### 在 Python 中使用了什么 在这个应用环境中,我使用了 Python 3.7 和这些模块: - PyYAML=1.0.0 - chatterbot>=1.0.0 - chatterbot-corpus>=1.2.0 - SQLAlchemy>=1.2 - ./nativeAPI_wheel/irisnative-1.0.0-cp34-abi3-linux_x86_64.whl ### 项目结构 本项目具有简单易懂的结构。 在主文件夹上,有 3 个最重要的子文件夹: - ./app:具有全部**应用代码**和安装配置。 - ./iris:具有 **InterSystems IRIS dockerfile**,准备服务于应用。 - ./data:通过一个**卷**将主机链接到容器环境 ### 应用结构 现在,可以在 ./app 目录下看到一些文件: - chatbot.py:具有 Web 应用实现 - iris_python_suite.py:具有一些加速器的类,通过 IRIS Native API 与 IRIS 数据库和 Python 搭配使用。 ### 数据库结构 此应用使用 Intersystems IRIS 作为存储库,使用的 globals 包括: - ^chatbot.training.data:以问题和答案的形式存储所有自定义训练数据。 - ^chatbot.conversation:存储所有对话有效负载。 - ^chatbot.training.isupdated:控制训练管道。 ### 其他解决方案的产品 我没有为所有对话创建报告,但这不是什么问题,使用全局图形查看器即可跟踪对话。 ![图片](https://raw.githubusercontent.com/renatobanzai/iris-python-covid19/master/img/conversations.png) ## 亲自运行应用 ### 先决条件 * git * docker 和 docker-compose(以及 docker 中更多的内存设置,至少 4GB) * 在您的环境中访问终端 ### 步骤 使用 docker-compose,您可以在一个环境中将所有组件和配置轻松转到 iris-python-covid19 文件夹,键入: ``` $ docker compose build $ docker compose up ``` ### 估计转入容器的时间 第一次运行将通过网络链接下载图像和依赖项。 如果持续时间超过 15 分钟,那可能是出现了问题,请随时来这里留言。 第一次运行后,下一次运行会好很多,只需要不到 2 分钟。 ### 如果一切正常 一段时间后,您可以打开浏览器并转到地址: 训练数据表单 ``` http://localhost:8050/chatbot-training-data ``` 聊天机器人 ``` http://localhost:8080 ``` ### 您应该查看 IRIS 管理门户 我暂时使用的是 USER 命名空间 ``` http://localhost:9092 user: _SYSTEM pass: theansweris42 ``` ### 如果本文对您有帮助或者有您喜欢的内容,请投票: 此应用目前正在参与 Open Exchange 竞赛,您可以在这里给我的应用 **iris-python-suite** 投票 (https://openexchange.intersystems.com/contest/current)
公告
Johnny Wang · 十二月 23, 2021

快来报名→首届全国医疗健康信息互联互通与智慧医院建设大会

12月25日-26日,首届全国医疗健康信息互联互通与智慧医院建设大会即将拉开帷幕!本次会议以“互联互通——通向智慧医院的桥梁”为主题,将采用线上形式召开。 会议分为两大部分(点击“阅读原文”查看全部日程及报名方式) #12月25日# 开幕式及综合论坛 12月25日,会议包含丰富的主题演讲,以及如下首发与启动仪式: 1. 中文医学术语(含中医)系统:首发面向联盟医疗机构提供中文医学术语(含中医)标准集和知识图谱等系统资源的访问服务,推进术语标准落地和发展,为我国智慧医院建设提供可持续的信息化支撑。 2. 2021年度医疗健康信息化企业影响力榜单:榜单聚焦医疗健康信息化企业,围绕医疗健康信息化软件产品,从企业的市场规模、企业形象、产品服务、技术创新等多个维度,全方位展示企业综合影响力,宣传推广优秀企业品牌,促进医疗信息化市场良性竞争,更好地为医院高质量发展提供信息化服务。 3. 启动“互联互通促进智慧医院建设”征文活动:总结近年来医院信息互联互通建设成效,梳理医院高质量发展路径,探讨医疗健康信息互联互通在促进电子病历、智慧服务、智慧管理“三位一体”智慧医院建设中的作用和成效。 4. 启动全国医疗健康首席数据官能力提升项目:以数据赋能与创新驱动为理念,融合多元知识和技能体系,通过课堂授课、沙龙研讨、案例分析、实地考察等立体化培训形式,提升医疗健康首席数据官实施数据战略、建设数据资源、保障数据安全、管理数据资产、创造数据价值的能力。 #12月26日# 六大平行论坛 12月26日上午 专题论坛——以质量为根本的智慧临床 医院电子病历建设与应用、医院集成平台建设与发展、新一代医院数据中心建设、医学人工智能与临床决策支持; 专题论坛——以需求为导向的智慧服务 医院智慧服务与便民惠民、互联网医院建设与发展/互联网+医疗健康建设与发展、远程医疗建设与应用; 专题论坛——以精细为特征的智慧管理 医院智慧运营管理、物联网创新应用与智慧后勤、公立医院绩效考核; 12月26日下午 专题论坛——以价值为核心的数据治理 医院数据治理建设与应用、大数据平台与数据建模、临床科研信息化建设、医疗健康数据利用与挖掘; 专题论坛——以主动为方向的网络安全 医院信息安全规划与建设、互联网+医疗健康安全建设、医院数据安全建设与管理; 专题论坛——以标准为基础的测评培训 医院信息互联互通测评方案解读、迎评促建筹备注意事项、互联互通测评经验分享与创新实践。InterSystems将在此分论坛中进行技术分享。 #InterSystems 技术分享# 从软件和集成架构的发展看互联互通 演讲人:乔鹏 InterSystems中国技术总监 乔鹏对于数据库、医疗相关标准以及集成平台解决方案,有着深刻的理解和十多年的行业经验,参与主导过百余家医院或者区域平台的信息化建设,同时对CDR、临床决策支持、商业智能、机器学习等数据利用产品和方案有深刻的洞察和丰富的实践经验。 演讲主题:从软件和集成架构的发展看互联互通 目前互联互通的实现架构类型不少,这些架构各自有哪些优点和缺点?是否满足不断发展的互联互通需求?医院在考虑这些架构时要注意哪些事项?有没有最佳实践?此次技术分享将从软件和集成架构的发展历史和趋势分析互联互通,并尝试回答这些问题。 专题论坛“以标准为基础的测评培训” 详细日程 阅读原文(查看大会详细日程 | 报名参会)
文章
yaoguai wan · 九月 30, 2022

IRIS架构的浅显理解以及windows10、docker安装IRIS Health详解流程及部分问题浅析

前言 本人因技术需要,了解到了IRIS Health产品,在听了产品介绍会之后,感觉该产品是否有趣,并且比较符合自己目前的需求,因此大概了解了下IRIS的架构。以下是本人的浅显理解,如有错误之处欢迎讨论。 本人从产品介绍和社区的文档中,了解到IRIS的大概功能分类 InterSystems IRIS是一款数据平台,适用于软甲开发人员 基于FHIR 整合医疗全流程数据,通过机器学习和人工智能分析 业务优化 数据管理 Sharding数据分片技术 分布式架构 IRIS互操作性 数据分析能力 IRIS对FHIR的支持 机器学习与自动化 其中结合到自己想要研究的领域,想要探索是否可以利用该产品并结合其他工具开发一套通用的专病数据库构建及应用方法。 我目前对该产品的初步定位是对自行提供的数据集合的存储和处理,其中提供包括编码规范、高效存储架构、编程接口、算法在内的辅助工具。针对数据的处理和应用,该产品做的很完善,但是对于数据的获取,例如是否支持extract-transformation-load功能,或者能否利用自定义编程接口实现流批一体化数据抽取。根据上述两个问题,第一步需要安装该产品,所以本人根据社区官网上相关的安装教程进行了安装实验,在此期间发现了社区的教程有些简单并且有些关键点很容易被忽视本人在安装过程中就遇到过一个和系联的工程师讨论了一段时间之后才发现的,因此想与大家分享下安装过程中遇到的一些问题,避免一些问题后,安装过程还是很简单的,傻瓜式操作,后面可以分享下我的安装命令。 问题分享 首先注意产品的平台基本要求,这是平台操作手册上讲的,一定要严格遵守否则会报各种奇怪的错误,IRIS对不同版本的操作系统间的兼容性还有比较严格的,要注意,操作系统和后面容器的配合,我遇到的一个问题就是操作系统的版本和容器的版本不一致导致安装失败。 1、使用docker安装IRIS Health 安装平台介绍:Ubuntu18.04及docker 20.10 要求满足的容器版本20.04 安装过程中遇到的问题:注意linux的发行版本,必须严格遵守,本人在安装过程中最开始使用的是Ubuntu20,使用docker pull containers.intersystems.com/intersystems/iris-community:2022.1.0.209.0 命令可以顺利拉取镜像,但是在启动容器的过程中,一直失败,参考社区中有关启动失败时,设置cpu等限制sudo docker run --name my-iris --cpuset-cpus 0-7 -d store/intersystems/iris-community:2021.2.0.649.0,同样失败,最后发现是ubuntu的版本问题导致的,我最开始只关注了docker的版本,后来使用ubuntu18.04,即可顺利拉取镜像并启动容器。 附:1、查看ubuntu版本命令 cat /proc/version 2、查看docker版本命令 dicker version 2、windows安装IRIS Health 安装平台介绍:windows10(64位) 硬件介绍:16核cpu,32G运存,500G存储。注:因为本人采用的是虚拟机,所以各项配置初始时调整的很高,安装后发现社区版对各种性能有限制,例如cpu最多用8个,内存限制等,所以硬件环境无需太高,但是也不能太低,像windows10这种,首先要保证系统可以顺利安装, 在配置方面,Win10的配置要求其实并不高,具体配置如下: CPU:1GHz或更快的处理器   RAM:1GB(32位)或2GB(64位)   HDD:16GB(32位操作系统)或20GB(64位操作系统)   显卡:DirectX 9或更高版本(包含WDDM 1.0驱动程序)   显示器:1024x600分辨率   简而言之,只要满足或者高于以上要求即可安装。 但是考虑到iris还要占用很大一块运存和存储,所以windows10最少得4G运存和200G存储,这样系统运行不会太卡,iris运行速度也算可以(这个速度我只测试没有运行处理任务的速度)。 安装过程中遇到的问题:1、注意windows10的位数不要安装32位的操作系统,同时IRIS不支持windows7,一开始没注意,一直安装失败。 windows确定操作系统版本以及位数的命令不在赘述,google一下,很简单。 下一步计划 平台建好以后开始考虑数据的获取,下一步首先继续熟悉iris产品架构,然后尝试能否实现ETL与IRIS的对接。 好文,期待下一步分享! linux的安装可以参考一下马老师写的这篇文章https://cn.community.intersystems.com/node/516631,很nice
文章
姚 鑫 · 四月 6, 2021

第十八章 定义和使用存储过程

# 第十八章 定义和使用存储过程 本章介绍如何在IntersystemsIRIS®数据平台上定义和使用Intersystems SQL中的存储过程。它讨论了以下内容: - 存储过程类型的概述 - 如何定义存储过程 - 如何使用存储过程如 - 何列出存储过程及其参数。 # 概述 SQL例程是可执行的代码单元,可以由SQL查询处理器调用。 SQL例程有两种类型:功能和存储过程。从支持`FunctionName()`语法的任何SQL语句中调用函数。存储过程只能由`CALL`语句调用。函数接受某些输入定向参数并返回单个结果值。存储过程接受某些输入,输入输出和输出参数。存储过程可以是用户定义的函数,返回单个值。 `CALL`语句也可以调用函数。 与大多数关系数据库系统一样,Intersystems Iris允许创建SQL存储过程。存储过程(SP)提供存储在数据库中的可调用可调用的程序,并且可以在SQL上下文中调用(例如,通过使用呼叫语句或通过ODBC或JDBC)。 与关系数据库不同,Intersystems Iris使可以将存储过程定义为类的方法。实际上,存储过程只不过是SQL可用的类方法。在存储过程中,可以使用基于对象的全系列Intersystems的功能。 - 可以通过查询数据库将存储过程定义为返回单个结果集数据集的查询。 - 可以将存储过程定义为可以用作用户定义函数的函数过程,返回单个值。 - 可以将存储过程定义为可以修改数据库数据并返回单个值或一个或多个结果集的方法。 可以确定使用 `$SYSTEM.SQL.Schema.ProcedureExists()`方法是否已存在该过程。此方法还返回过程类型:`“函数function”`或`“查询query”`。 # 定义存储过程 与Intersystems SQL的大多数方面一样,有两种方法可以定义存储过程:使用DDL和使用类。这些在以下部分中描述。 ## 使用DDL定义存储过程 Intersystems SQL支持以下命令来创建查询: - `CREATE PROCEDURE`可以创建始终作为存储过程投影的查询。 查询可以返回单个结果集。 - `CREATE QUERY`创建一个查询,该查询可以选择性地投影为存储过程。 查询可以返回单个结果集。 InterSystems SQL支持以下命令来创建方法或函数: - `CREATE PROCEDURE`可以创建始终作为存储过程投影的方法。 方法可以返回单个值,也可以返回一个或多个结果集。 - `CREATE METHOD`可以创建一个方法,该方法可以选择投影为存储过程。 方法可以返回单个值,也可以返回一个或多个结果集。 - `CREATE FUNCTION`可以创建一个函数过程,该函数过程可以选择投影为存储过程。 函数可以返回单个值。 这些命令中指定的可执行代码块可以用InterSystems SQL或ObjectScript编写。 可以在ObjectScript代码块中包含嵌入式SQL。 ## SQL到类名转换 使用DDL创建存储过程时,指定的名称将转换为类名。 如果类不存在,系统将创建它。 - 如果名称是不限定的,并且没有提供FOR子句:使用系统范围的默认模式名作为包名,后跟一个点,后跟一个生成的类名,由字符串 `‘func’`, `‘meth’`, `‘proc’`, or `‘query’`组成,后跟去掉标点字符的SQL名。 例如,未限定的过程名`Store_Name`会产生如下类名`User.procStoreName`: 这个过程类包含方法`StoreName()`。 - 如果名称是限定的,并且没有提供`FOR`子句:模式名被转换为包名,后跟一个点,后跟字符串`‘func’`, `‘meth’`,` ‘proc’`, or `‘query’` ,后跟去掉标点字符的SQL名。 如果需要,将指定的包名转换为有效的包名。 如果名称是限定的,并且提供了`FOR`子句:在`FOR`子句中指定的限定类名将覆盖在函数、方法、过程或查询名称中指定的模式名。 - SQL存储过程名称遵循标识符命名约定。 InterSystems IRIS从SQL名称中去除标点字符,从而为过程类及其类方法生成唯一的类实体名称。 下面的规则管理模式名到有效包名的转换: - 如果架构名称包含下划线,则此字符将转换为点,表示子包。例如,合格的名称`myprocs.myname`创建包`myprocs`。限定名称`my_procs.myname`创建了包含子包`procs`的包。 以下示例显示了标点符号在类名和SQL调用中的不同之处。它定义了一个包含包含两个点的类名的方法。从SQL中调用时,示例将第一个点替换为下划线字符: ```java Class Sample.ProcTest Extends %RegisteredObject { ClassMethod myfunc(dummy As %String) As %String [ SqlProc ] { /* method code */ Quit "abc" } } ``` ```java SELECT Sample.ProcTest_myfunc(Name) FROM Sample.Person ``` ## 使用类定义方法存储过程 类方法可以公开为存储过程。 这些是不返回数据的操作的理想选择,例如计算值并将其存储在数据库中的存储过程。 几乎所有类都可以将方法公开为存储过程; 例外是生成器类,比如数据类型类(`[ClassType = datatype]`)。 生成器类没有运行时上下文。 只有在其他实体(如属性)的运行时中使用数据类型上下文才有效。 **要定义方法存储过程,只需定义一个类方法并设置其`SqlProc`关键字:** ```java Class MyApp.Person Extends %Persistent [DdlAllowed] { /// This procedure finds total sales for a territory ClassMethod FindTotal(territory As %String) As %Integer [SqlProc] { // use embedded sql to find total sales &sql(SELECT SUM(SalesAmount) INTO :total FROM Sales WHERE Territory = :territory ) Quit total } } ``` 编译这个类之后,`FindTotal()`方法将作为存储过程`MyApp.Person_FindTotal()`投影到SQL中。 可以使用方法的`SqlName`关键字更改SQL对过程使用的名称。 该方法使用过程上下文处理程序在过程及其调用者(例如,ODBC服务器)之间来回传递过程上下文。 这个过程上下文处理程序是由InterSystems IRIS(作为`%qHandle:%SQLProcContext`)使用%`sqlcontext`对象自动生成的。 `%sqlcontext`由`SQLCODE`错误状态、SQL行数、错误消息等属性组成,使用相应的SQL变量设置,如下所示: ```java SET %sqlcontext.%SQLCode=SQLCODE SET %sqlcontext.%ROWCOUNT=%ROWCOUNT SET %sqlcontext.%Message=%msg ``` 不需要对这些值做任何事情,但是它们的值将由客户机解释。 在每次执行之前都会重置`%sqlcontext`对象。 该方法不应该返回任何值。 一个类的用户定义方法的最大数目是`2000`个。 例如,假设有一个`CalcAvgScore()`方法: ```java ClassMethod CalcAvgScore(firstname As %String,lastname As %String) [sqlproc] { New SQLCODE,%ROWID &sql(UPDATE students SET avgscore = (SELECT AVG(sc.score) FROM scores sc, students st WHERE sc.student_id=st.student_id AND st.lastname=:lastname AND st.firstname=:firstname) WHERE students.lastname=:lastname AND students.firstname=:firstname) IF ($GET(%sqlcontext)'= "") { SET %sqlcontext.%SQLCODE = SQLCODE SET %sqlcontext.%ROWCOUNT = %ROWCOUNT } QUIT } ``` ## 使用类定义查询存储过程 许多从数据库返回数据的存储过程可以通过标准查询接口实现。 只要可以用嵌入式SQL编写过程,这种方法就可以很好地工作。 注意,在以下示例中,使用了嵌入式SQL `host`变量为`WHERE`子句提供一个值: ```java Class MyApp.Person Extends %Persistent [DdlAllowed] { /// This procedure result set is the persons in a specified Home_State, ordered by Name Query ListPersons(state As %String = "") As %SQLQuery [ SqlProc ] { SELECT ID,Name,Home_State FROM Sample.Person WHERE Home_State = :state ORDER BY Name } } ``` 要将查询公开为存储过程,可以将Studio Inspector条目中的`SQLProc`字段的值更改为`True`,或者在查询定义中添加以下`“[SQLProc]”`字符串: ```java Query QueryName() As %SQLQuery( ... query definition ... ) [ SqlProc ] ``` 编译这个类之后,`ListPersons`查询将作为存储过程`MyApp.Person_ListPersons`投影到SQL中。 可以使用查询的`SqlName`关键字更改SQL用于该过程的名称。 当`MyApp`。 从SQL调用`Person_ListPersons`,它将自动返回由查询的SQL语句定义的结果集。 下面是一个使用结果集的存储过程的示例: ```java Class apc.OpiLLS.SpCollectResults1 [ Abstract ] { /// This SP returns a number of rows (pNumRecs) from WebService.LLSResults, and updates a property for each record Query MyQuery(pNumRecs As %Integer) As %Query(ROWSPEC = "Name:%String,DOB:%Date") [ SqlProc ] { } /// You put initial code here in the Execute method ClassMethod MyQueryExecute(ByRef qHandle As %Binary, pNumRecs As %Integer) As %Status { SET mysql="SELECT TOP ? Name,DOB FROM Sample.Person" SET rset=##class(%SQL.Statement).%ExecDirect(,mysql,pNumRecs) IF rset.%SQLCODE'=0 {QUIT rset.%SQLCODE} SET qHandle=rset QUIT $$$OK } /// This code is called by the SQL framework for each row, until no more rows are returned ClassMethod MyQueryFetch(ByRef qHandle As %Binary, ByRef Row As %List, ByRef AtEnd As %Integer = 0) As %Status [ PlaceAfter = NewQuery1Execute ] { SET rset=qHandle SET tSC=$$$OK FOR { ///Get next row, quit if end of result set IF 'rset.%Next() { SET Row = "", AtEnd = 1 SET tSC=$$$OK QUIT } SET name=rset.Name SET dob=rset.DOB SET Row = $LISTBUILD(name,dob) QUIT } QUIT tSC } ClassMethod MyQueryClose(ByRef qHandle As %Binary) As %Status [ PlaceAfter = NewQuery1Execute ] { KILL qHandle //probably not necesary as killed by the SQL Call framework QUIT $$$OK } } ``` 如果可以将查询编写为一个简单的SQL语句并通过查询向导创建它,那么就不需要了解实现查询的底层方法。 在后台,对于每个查询,类编译器都会根据存储过程的名称生成方法,包括: - `stored-procedure-nameExecute()` - `stored-procedure-nameFetch()` - `stored-procedure-nameFetchRows()` - `stored-procedure-nameGetInfo()` - `stored-procedure-nameClose()` 如果查询类型为`%SQLQuery`,则类编译器会自动将一些嵌入式SQL插入到生成的方法中。 `Execute()`为SQL声明并打开存储的游标。 `Fetch()`被反复调用,直到它返回一个空行`(SET row ="")`。 还可以选择让`Fetch()`返回一个`AtEnd=1`布尔标志,以表明当前获取构成最后一行,下一个获取预期返回空行。 然而,应该总是使用空行`(row ="")`作为测试,以确定结果集何时结束; 当设置`AtEnd=1`时,应该始终设置`Row=""`。 `FetchRows()`在逻辑上等同于反复调用`Fetch()`。 调用`GetInfo()`返回存储过程签名的详细信息。 `Close()`关闭游标。 当从客户机调用存储过程时,会自动调用所有这些方法,但理论上可以从运行在服务器上的ObjectScript直接调用这些方法。 要将对象从`Execute()`传递给`Fetch()`,或从`Fetch()`传递给下一次调用`Fetch()`,可以将查询处理程序设置为希望传递的对象的对象引用(`oref`)。 要传递多个对象,可以将`qHandle`设置为一个数组: ```java SET qHandle(1)=oref1,qHandle(2)=oref2 ``` 可以基于自定义编写的代码(而不是SQL语句)创建结果集存储过程。 对一个类的用户定义查询`Query`的最大数目是200。 ## 自定义Query 对于复杂的查询或不适合查询模型的存储过程,通常需要通过替换查询的部分或全部方法来自定义查询。 你可以使用 `%Library.Query`。 如果选择类型`%query` (`%Library.Query`)而不是`%SQLQuery` (`%Library.SQLQuery`),则通常更容易实现查询。 这生成了相同的5个方法,但是现在`FetchRows()`只是重复调用`Fetch()` (`%SQLQuery`进行了一些优化,导致了其他行为)。 `GetInfo()`只是从签名中获取信息,因此代码不太可能需要更改。 这将问题简化为为其他三个类中的每一个创建类方法。 请注意,在编译类时,编译器会检测到这些方法的存在,而不会覆盖它们。 **这些方法需要特定的签名:它们都接受类型为`%Binary`的`Qhandle`(查询处理程序)。 这是一个指向保存查询的性质和状态的结构的指针。 它通过引用传递给`Execute()`和`Fetch()`,通过值传递给`Close()`:** ```java ClassMethod SP1Close(qHandle As %Binary) As %Status { // ... } ClassMethod SP1Execute(ByRef qHandle As %Binary, p1 As %String) As %Status { // ... } ClassMethod SP1Fetch(ByRef qHandle As %Binary, ByRef Row As %List, ByRef AtEnd As %Integer=0) As %Status { // ... } Query SP1(p1 As %String) As %Query(CONTAINID=0,ROWSPEC="lastname:%String") [sqlproc ] { } ``` 代码通常包括SQL游标的声明和使用。 从类型为`%SQLQuery`的查询中生成的游标自动具有诸如`Q14`这样的名称。 必须确保查询具有不同的名称。 在尝试使用游标之前,类编译器必须找到游标声明。 因此,`DECLARE`语句(通常在`Execute`中)必须与`Close`和`Fetch`语句在同一个MAC例程中,并且必须出现在它们中的任何一个之前。 直接编辑源代码,**在`Close`和`Fetch`定义中都使用方法关键字`PLACEAFTER`,以确保实现这一点。** 错误消息引用内部游标名,它通常有一个额外的数字。 因此,游标`Q140`的错误消息可能指向`Q14` # 使用存储过程 使用存储过程有两种不同的方式: - 可以使用SQL `CALL`语句调用存储过程; - 可以像使用SQL查询中的内置函数一样使用存储函数(即返回单个值的基于方法的存储过程)。 - 注意:当执行一个以SQL函数为参数的存储过程时,请使用`CALL`调用存储过程,示例如下: ``` CALL sp.MyProc(CURRENT_DATE) ``` **`SELECT`查询不支持执行带有SQL函数参数的存储过程。 `SELECT`支持执行带有SQL函数参数的存储函数。** `xDBC`不支持使用`SELECT`或`CALL`来执行带有SQL函数参数的存储过程。 ## 存储方法 存储函数是返回单个值的基于方法的存储过程。 例如,下面的类定义了一个存储函数`Square`,它返回给定值的平方: ```java Class MyApp.Utils Extends %Persistent [DdlAllowed] { ClassMethod Square(val As %Integer) As %Integer [SqlProc] { Quit val * val } } ``` 存储的函数只是指定了`SqlProc`关键字的类方法。 注意:对于存储的函数,`ReturnResultsets`关键字必须不指定(默认)或以关键字`not`作为开头。 可以在SQL查询中使用存储函数,就像使用内置SQL函数一样。 函数的名称是存储函数(在本例中为`“Square”`)的SQL名称,该名称由定义该函数的模式(包)名称限定(在本例中为`“MyApp”`)。 下面的查询使用了`Square`函数: ```sql SELECT Cost, MyApp.Utils_Square(Cost) As SquareCost FROM Products ``` 如果在同一个包(模式)中定义了多个存储函数,则必须确保它们具有惟一的SQL名称。 下面的示例定义了一个名为`Sample`的表。 具有两个定义的数据字段(属性)和两个定义的存储函数`TimePlus`和`DTime`的工资: ```java Class Sample.Wages Extends %Persistent [ DdlAllowed ] { Property Name As %String(MAXLEN = 50) [ Required ]; Property Salary As %Integer; ClassMethod TimePlus(val As %Integer) As %Integer [ SqlProc ] { QUIT val * 1.5 } ClassMethod DTime(val As %Integer) As %Integer [ SqlProc ] { QUIT val * 2 } } ``` 下面的查询使用这些存储过程返回同一个表`Sample.Wages`中每个员工的`Salary`、`time- half`和`double time`工资率: ```java SELECT Name,Salary, Sample.Wages_TimePlus(Salary) AS Overtime, Sample.Wages_DTime(Salary) AS DoubleTime FROM Sample.Wages ``` 下面的查询使用这些存储过程返回不同表`Sample.Employee`中每个员工的`Salary`、`time- half`和`double time`工资率: ``` SELECT Name,Salary, Sample.Wages_TimePlus(Salary) AS Overtime, Sample.Wages_DTime(Salary) AS DoubleTime FROM Sample.Employee ``` ## 权限 要执行一个过程,用户必须具有该过程的`execute`权限。 使用`GRANT`命令或`$SYSTEM.SQL.Security.GrantPrivilege()`方法将指定过程的执行权限分配给指定用户。 通过调用`$SYSTEM.SQL.Security.CheckPrivilege()`方法,可以确定指定的用户是否具有指定过程的执行权限。 要列出用户具有`EXECUTE`权限的所有过程,请转到管理门户。 从系统管理中选择Security,然后选择Users或Roles。 为所需的用户或角色选择Edit,然后选择SQL Procedures选项卡。 从下拉列表中选择所需的名称空间。 # List 存储过程 `INFORMATION.SCHEMA.ROUTINES persistent`类显示关于当前命名空间中所有例程和过程的信息。 当在嵌入式SQL中指定时,`INFORMATION.SCHEMA`。 例程需要`#include %occInclude`宏预处理指令。 动态SQL不需要这个指令。 下面的例子返回例程名称、方法或查询名称、例程类型(过程或函数)、例程主体(`SQL=class query with SQL, EXTERNAL=not a class query with SQL`)、返回数据类型,以及当前命名空间中模式`“Sample”`中所有例程的例程定义: ```sql SELECT ROUTINE_NAME,METHOD_OR_QUERY_NAME,ROUTINE_TYPE,ROUTINE_BODY,SQL_DATA_ACCESS,IS_USER_DEFINED_CAST, DATA_TYPE||' '||CHARACTER_MAXIMUM_LENGTH AS Returns,NUMERIC_PRECISION||':'||NUMERIC_SCALE AS PrecisionScale, ROUTINE_DEFINITION FROM INFORMATION_SCHEMA.ROUTINES WHERE ROUTINE_SCHEMA='SQLUser' ``` ![image](/sites/default/files/inline/images/1_30.png) `INFORMATION.SCHEMA.PARAMETERS persistent`类显示关于当前命名空间中所有例程和过程的输入和输出参数的信息。 下面的示例返回例程名称、参数名称(不管是输入参数还是输出参数)以及当前命名空间中模式`“Sample”`中的所有例程的参数数据类型信息: ``` SELECT SPECIFIC_NAME,PARAMETER_NAME,PARAMETER_MODE,ORDINAL_POSITION, DATA_TYPE,CHARACTER_MAXIMUM_LENGTH AS MaxLen,NUMERIC_PRECISION||':'||NUMERIC_SCALE AS PrecisionScale FROM INFORMATION_SCHEMA.PARAMETERS WHERE SPECIFIC_SCHEMA='SQLUser' ``` ![image](/sites/default/files/inline/images/2_18.png) 使用管理门户SQL界面中的Catalog Details选项卡,可以为单个过程显示大部分相同的信息。 过程的目录详细信息包括过程类型(查询或函数)、类名称、方法或查询名称、描述以及输入和输出参数的数量。 目录详细信息存储过程信息显示还提供了运行存储过程的选项。
文章
姚 鑫 · 四月 24, 2021

第五章 优化查询性能(三)

# 第五章 优化查询性能(三) # 查询执行计划 可以使用解释或显示计划工具来显示`SELECT`、`DECLARE`、`UPDATE`、`DELETE`、`TRUNCATE TABLE`和一些`INSERT`操作的执行计划。这些操作统称为查询操作,因为它们使用`SELECT`查询作为其执行的一部分。InterSystems IRIS在准备查询操作时生成执行计划;不必实际执行查询来生成执行计划。 默认情况下,这些工具显示InterSystems IRIS认为的最佳查询计划。对于大多数查询,有多个可能的查询计划。除了InterSystems IRIS认为最佳的查询计划外,还可以生成和显示备用查询执行计划。 InterSystems IRIS提供以下查询计划工具: - `$SYSTEM.SQL.ExPlan()`方法可用于生成和显示`XML`格式的查询计划以及备选查询计划(可选)。 - SQL `EXPLAIN`命令可用于生成`XML`格式的查询计划,还可以选择生成备选查询计划和SQL统计信息。所有生成的查询计划和统计信息都包含在名为Plan的单个结果集字段中。请注意,`EXPLAIN`命令只能与`SELECT`查询一起使用。 - 管理门户 - >系统资源管理器 - >SQL界面显示计划按钮。 - 管理门户 — >系统资源管理器 — >工具—>SQL性能工具。 ![image](/sites/default/files/inline/images/1_40.png) 对于生成的`%PARALLEL`和分片查询,这些工具显示所有适用的查询计划。 ## 使用`Explain()`方法 可以通过运行`$SYSTEM.SQL.Explain()`方法生成查询执行计划,示例如下: ```java /// w ##class(PHA.TEST.SQL).SQLExplain() ClassMethod SQLExplain() { SET mysql=2 SET mysql(1)="SELECT TOP 10 Name,DOB FROM Sample.Person " SET mysql(2)="WHERE Name [ 'A' ORDER BY Age" SET status=$SYSTEM.SQL.Explain(.mysql,{"all":0,"quiet":1,"stats":0,"preparse":0},,.plan) IF status'=1 {WRITE "Explain() failed:" DO $System.Status.DisplayError(status) QUIT} ZWRITE plan } ``` 设置`“all”:0`选项会生成InterSystems IRIS认为最优的查询计划。 设置`“all”:1`选项会生成最佳的查询计划和备选的查询计划。 默认值为`“all”:0`。 结果被格式化为表示`xml`格式文本的下标数组。 如果指定单个查询计划`("all":0)`,上述方法调用中的plan变量将具有以下格式: - `plan`:显示结果中的下标总数。 - `plan(1)`:总是包含XML格式标签`“”`。 最后一个下标总是包含XML格式标记`“”`。 - `plan(2)`:总是包含XML格式标签`""` - `plan(3)`: 总是包含查询文本的第一行。 如果"`"preparse":0`(默认值),则返回字面查询文本,并为多行查询的每一行使用额外的下标;在上面的例子中,查询有两行,因此使用了两个下标`(plan(3)`和`plan(4)`)。如果`"prepare":1`,则规范化查询文本返回为单行`:plan(3)`。 - `plan(n)`:总是包含XML格式标签`“”`; 在上面的例子中,`3+mysql = plan(5)`。 - `plan(n+1)`:总是包含XML格式的查询`cost""`. - `plan(n+2)`:总是包含执行计划的第一行。 这个plan可以是任何长度,可以包含`…`标签作为单独的下标行,包含生成的执行模块的查询计划。 如果指`"all":1 Explain()`将生成备用查询计划。计划变量遵循相同的格式,不同之处在于它们使用第一级下标来标识查询计划,而使用第二级下标来标识查询计划的行。因此,`plan(1)`包含第一个查询计划结果中的二级下标计数,`plan(2)`包含第二个查询计划结果中的二级下标计数,依此类推。在此格式中,`plan(1,1)`包含第一个查询计划的`XML`格式标记 `""`;`plan(2,1)`包含第二个查询计划的XML格式标记 `""`,依此类推。唯一不同的是,备用查询计划包含二级零下标(`plan(1,0)`变量,该变量包含成本和索引信息;此零下标不计入一级下标(`plan(1)`)值。 如果指`"stats":1`, `Explain()`将为每个查询计划模块生成性能统计信息。 每个模块的这些统计数据都使用` ... `标记,并立即出现在查询成本之后(`""`)和查询计划文本之前。 如果查询计划包含额外的``标记,则生成的模块的``将紧接在``标记之后,在该模块的查询计划之前列出。 对于每个模块,将返回以下项: - ``:模块名。 - ``:模块的总执行时间,以秒为单位。 - ``:全局引用的计数。 - ``:执行的代码行数。 - ``:磁盘等待时间,单位为秒。 - ``:结果集中的行数。 - ``:此模块被执行的次数。 - ``:这个程序被执行的次数。 ## 使用显示计划从InterSystems SQL工具 可以使用`Show Plan`以以下任何一种方式显示查询的执行计划 - 从管理门户SQL接口。 选择`System Explorer`,然后选择SQL。 在页面顶部选择带有`Switch`选项的名称空间。 (可以为每个用户设置管理门户的默认名称空间。) 编写查询,然后按`Show Plan`按钮。 (还可以通过单击列出查询的`Plan`选项,从`Show History`列表调用`Show Plan`。) - 从管理门户工具界面。 选择“系统资源管理器”,然后选择“工具”,然后选择“SQL性能工具”,然后选择“SQL运行时统计信息”: - 在`Query Test`选项卡中:在页面顶部选择一个带有`Switch`选项的名称空间。 在文本框中写入查询。 然后按下`Show Plan with SQL Stats`按钮。 这将在不执行查询的情况下生成一个显示计划。 - 在`View Stats`选项卡中:对于列出的查询之一,按`Show Plan`按钮。 列出的查询包括在执行查询时编写的查询和在查询测试时编写的查询。 - 在`SQL Shell`中,可以使用`SHOW PLAN`和`SHOW PLANALT Shell`命令来显示最近执行的查询的执行计划。 - 通过对缓存的查询结果集运行`Show Plan`,使用:`i%Prop`语法将文本替换值存储为属性: ```java SET cqsql=2 SET cqsql(1)="SELECT TOP :i%PropTopNum Name,DOB FROM Sample.Person " SET cqsql(2)="WHERE Name [ :i%PropPersonName ORDER BY Age" DO ShowPlan^%apiSQL(.cqsql,0,"",0,$LB("Sample"),"",1) ``` 默认情况下,`Show Plan`以逻辑模式返回值。但是,当从管理门户或SQL Shell调用`Show Plan`时,`Show Plan`使用运行时模式。 ## 执行计划:语句文本和查询计划 显示计划执行计划由两个组件组成,即语句文本和查询计划: 语句文本复制了原始查询,但进行了以下修改:管理门户SQL界面中的显示计划按钮显示删除了注释和换行符的SQL语句。空格是标准化的。显示计划按钮显示还执行文字替换,将每个文字替换为`?`,除非已通过将文字值括在双圆括号中来取消文字替换。使用`EXPLAIN()`方法显示显示计划时,或者使用SQL运行时统计信息或备用显示计划工具显示显示计划时,不会执行这些修改。 查询计划显示将用于执行查询的计划。查询计划可以包括以下内容: - 如果查询计划已经冻结,则查询计划的第一行为冻结计划,否则第一行为空。 - `“Relative cost”`是一个整数值,它是从许多因素中计算出来的抽象数字,用于比较同一查询的不同执行计划的效率。 这种计算考虑了查询的复杂性、索引的存在和表的大小(以及其他因素)。 相对成本对于比较两个不同的查询是没有用的。 `" Relative cost not available"`由某些聚合查询返回,例如`COUNT(*)`或`MAX(%ID)`不带`WHERE`子句。 - 查询计划由一个主模块和(在需要时)一个或多个子组件组成。 可以显示一个或多个模块子组件,按字母顺序命名, `B: Module:B`, `Module:C`,等等开始,并按执行顺序列出(不一定按字母顺序)。 默认情况下,模块执行处理并使用其结果填充内部临时文件(内部临时表)。 通过指定 `/*#OPTIONS {"NoTempFile":1} */`,可以强制查询优化器创建不生成内部临时文件的查询计划,如注释选项中所述。 对于查询中的每个子查询,都会显示一个命名子查询模块。子查询模块按字母顺序命名。子查询命名在每个命名子查询之前跳过一个或多个字母。因此 `Module:B`, `Subquery:F or Module:D`, `Subquery:G`.当到达字母表末尾时,会对其他子查询进行编号,解析`Z=26`并使用相同的跳过序列。下面的示例是以`Subquery`开头的每三个子查询命名序列`:F:F,I,L,O,R,U,X,27,30,33`。下面的示例是以`Subquery`开头的每秒一次的子查询命名序列`:G:G,I,K,M,O,Q,S,U,W,Y,27,29`。如果子查询调用模块,模块将按字母顺序放在子查询之后,不会跳过。因此,`Subquery:H calls Module:I`。 - `“Read master map”`作为主模块中的第一个项目符号表示查询计划效率低下。查询计划使用以下映射类型语句之一开始执行`Read master map... (no available index), Read index map... (use available index), or Generate a stream of idkey values using the multi-index combination...`因为`master map`读取的是数据本身,而不是数据的索引,所以`Read master map...`。几乎总是指示低效的查询计划。除非表相对较小,否则应该定义一个索引,以便在重新生成查询计划时,第一个映射显示为`read index map...`。 某些操作会创建表示无法生成查询计划的显示计划: - 非查询插入:`INSERT... VALUES()`命令不执行查询,因此不生成查询计划。 - 查询总是`FALSE`:在少数情况下,InterSystems IRIS可以在准备查询时确定查询条件总是`FALSE`,因此不能返回数据。“显示计划”会在“查询计划”组件中通知这种情况。例如,包含条件的查询`WHERE %ID IS NULL 或 WHERE Name %STARTSWITH('A') AND Name IS NULL `不能返回数据,因此,InterSystems IRIS不生成执行计划。查询计划没有生成执行计划,而是表示`“Output no rows”`。如果查询包含具有这些条件之一的子查询,则查询计划的子查询模块表示`“Subquery result NULL, found no rows”`。这种条件检查仅限于涉及`NULL`的几种情况,并不是为了捕捉所有自相矛盾的查询条件。 - 无效的查询:`Show Plan`为大多数无效查询显示`SQLCODE错误消息`。然而,在少数情况下,`Show Plan`显示为空。例如, `WHERE Name = $$$$$ or WHERE Name %STARTSWITH('A")`。在这些情况下,`Show Plan`不显示语句文本,而`Query Plan[没有为该语句创建的计划]`。这通常发生在分隔文字的引号不平衡时。 当为用户定义的(“外部”)函数指定了两个或多个前置美元符号而没有指定正确的语法时,也会出现这种情况。 # 交替显示计划 可以使用管理门户或`Explain()`方法显示查询的替代执行计划。 使用以下任意一种方法,从管理门户显示查询的备选执行计划: - 选择系统资源管理器,选择工具,选择SQL性能工具,然后选择备用的显示计划。 - 选择`System Explorer`,选择SQL,然后从Tools下拉菜单中选择`Alternate Show Plans`。 ![image](/sites/default/files/inline/images/2_22.png) ![image](/sites/default/files/inline/images/3_18.png) 使用备用的“显示计划”工具: 1. 输入一个SQL查询文本,或使用`Show History`按钮检索一个。 可以通过单击右边的圆形“X”圆来清除查询文本字段。 2. 按显示计划选项按钮以显示多个备用显示计划。 `Run ... in the background...`默认情况下不选中复选框,这是大多数查询的首选设置。建议选择`RUN...`。对于大型或复杂的查询,请在后台复选框中。当一个长查询在后台运行时,会显示一个`View process`按钮。单击查看进程将在新选项卡中打开进程详细信息页面。在“进程详细信息”页中,可以查看进程,还可以挂起、继续或终止进程。 3. 可能的计划按成本升序列出,并带有映射类型和起始映射。 4. 从可能的计划列表中,使用复选框选择要比较的计划,然后按比较显示计划与统计信息按钮以运行这些计划并显示其SQL统计信息。 带有`ALL`限定符的`EXPLAIN()`方法显示查询的所有执行计划。它首先显示IRIS认为最优(成本最低)的计划,然后显示备选计划。备选计划按成本升序列出。 以下示例显示最佳执行计划,然后列出备选计划: ```java DO $SYSTEM.SQL.SetSQLStatsFlagJob(3) SET mysql=1 SET mysql(1)="SELECT TOP 4 Name,DOB FROM Sample.Person ORDER BY Age" DO $SYSTEM.SQL.Explain(.mysql,{"all":1},,.plan) ZWRITE plan ``` ## Stats 显示计划选项列表为每个备用显示计划分配一个成本值,使可以在执行计划之间进行相对比较。 `Alternate Show Plan Details`为每个查询计划提供了一组查询总数的统计信息(统计信息),以及(如果适用)每个查询计划模块的统计信息。每个模块的统计信息包括时间(整体性能,以秒为单位)、全局引用(全局引用数)、命令(执行的行数)和读取延迟(磁盘等待,以毫秒为单位)。查询总计统计信息还包括返回的行数。 # 将查询优化计划写入文件 以下实用程序列出了针对文本文件的一个或多个查询的查询优化计划。 ```java QOPlanner^%apiSQL(infile,outfile,eos,schemapath) ``` - `infile` 包含缓存查询列表的文本文件的文件路径名。指定为带引号的字符串。 - `outfile` 要列出查询优化计划的文件路径名。指定为带引号的字符串。如果该文件不存在,系统将创建该文件。如果该文件已存在,则InterSystems IRIS会覆盖该文件。 - `eos` 可选-语句末尾分隔符,用于分隔`Infile`列表中的各个缓存查询。指定为带引号的字符串。默认值为`“GO”`。如果此`EOS`字符串与缓存的查询分隔符不匹配,则不会生成输出文件。 - `schemapath` 可选-以逗号分隔的方案名列表,用于为未限定的表名、视图名或存储过程名指定方案搜索路径。可以包括`DEFAULT_SCHEMA`,这是当前系统范围内的默认架构。如果`infile`包含`#Import`指令,`QOPlanner`会将这些`#Import`包/架构名称添加到`schemapath`的末尾。 以下是调用此查询优化计划列表实用程序的示例。该实用程序将`ExportSQL^%qarDDLExport()`实用程序生成的文件作为输入,如“缓存查询”一章的“将缓存查询列出到文件”一节中所述。可以生成此查询列表文件,也可以将一个(或多个)查询写入文本文件。 ```java DO QOPlanner^%apiSQL("C:\temp\test\qcache.txt","C:\temp\test\qoplans.txt","GO") ``` 从终端命令行执行时,进度会显示在终端屏幕上,如下例所示: ```java Importing SQL Statements from file: C:\temp\test\qcache.txt Recording any errors to principal device and log file: C:\temp\test\qoplans.txt SQL statement to process (number 1): SELECT TOP ? P . Name , E . Name FROM Sample . Person AS P , Sample . Employee AS E ORDER BY E . Name Generating query plan...Done SQL statement to process (number 2): SELECT TOP ? P . Name , E . Name FROM %INORDER Sample . Person AS P NATURAL LEFT OUTER JOIN Sample . Employee AS E ORDER BY E . Name Generating query plan...Done Elapsed time: .16532 seconds ``` 创建的查询优化计划文件包含如下条目: ```java SELECT TOP ? P . Name , E . Name FROM Sample . Person AS P , Sample . Employee AS E ORDER BY E . Name Read index map Sample.Employee.NameIDX. Read index map Sample.Person.NameIDX. ###### SELECT TOP ? P . Name , E . Name FROM %INORDER Sample . Person AS P NATURAL LEFT OUTER JOIN Sample . Employee AS E ORDER BY E . Name Read master map Sample.Person.IDKEY. Read extent bitmap Sample.Employee.$Employee. Read master map Sample.Employee.IDKEY. Update the temp-file. Read the temp-file. Read master map Sample.Employee.IDKEY. Update the temp-file. Read the temp-file. ###### ``` 可以使用查询优化计划文本文件来比较使用不同查询变体生成的优化计划,或者比较不同版本的InterSystems IRIS之间的优化计划。 将SQL查询导出到文本文件时,来自类方法或类查询的查询将以代码行开头: ```java #import ``` 这个`#Import`语句告诉`QOPlanner`实用程序使用哪个默认包/模式来生成查询计划。从例程导出SQL查询时,例程代码中SQL语句之前的任何`#import`行也将位于导出文件中的SQL文本之前。假设从缓存查询导出到文本文件的查询包含完全限定的表引用;如果文本文件中的表引用不是完全限定的,则`QOPlanner`实用程序使用在运行`QOPlanner`时在系统上定义的系统范围的默认模式。