将压缩从 Node.js 推送到 SQL Server





4.00/5 (1投票)
在本文中,您将了解如何使用 GZip 算法在 SQL Server 中压缩数据,并通过 Node.js 将其发送到浏览器。
引言
GZIP 压缩在 Web 应用程序中很常用。如果您压缩要返回给浏览器文本,可以提高应用程序的性能。通常,您会从数据层获取原始结果,并在 Web 应用程序(例如 Node.js)中进行压缩。
SQL Server 2016 的一项新功能是内置的 GZip 压缩/解压缩函数,使您能够直接在数据库层压缩数据。SQL Server 提供了使用标准 GZip 算法压缩/解压缩数据的函数。与 GZip 算法兼容的一个好处是,您可以直接在 SQL Server 中压缩数据并将压缩后的数据传输给客户端。如果网络带宽是 Web 应用程序中的主要问题,并且您希望从数据层向浏览器发送 GZip 压缩的内容,这将有所帮助。
在此示例中,我将使用浏览器作为客户端,一个简单的 Node.js Web 应用程序,该应用程序仅从 SQL Server 读取压缩数据并将其流式传输到浏览器。
Using the Code
在此示例中,我将演示如何在由 Node.js、作为 Web 服务器组件的 Express 以及作为数据访问组件的 Tedious 实现的 Web 应用程序中使用 `COMPRESS` 函数。
如果您不知道如何设置 Node.js 站点,这里有一个简短的介绍。如果您熟悉 Node.js,请跳过此部分。
- 如果您还没有安装 Node.js,请安装它。这是一篇很好的文章,其中包含更多关于 Node.js 安装的详细信息。在此,我们将提供简短的说明,使用默认设置。
- 创建一个文件夹,用于存放您的 Node.js Web 应用程序。
- 进入该文件夹,并在命令行中运行 `npm init` 来设置 Node.js 应用程序。
- `npm` 命令会要求您输入一些项目设置,例如启动文件、作者、描述等。接受所有默认设置,将创建一个默认的 `package.json` 配置文件。
- 在您创建的文件夹中,从命令行运行 `npm install tedious` 以 安装用于 SQL Server 的 Tedious 连接器。
Tedious 是一个连接到 SQL Server 的简单框架。您只需要使用配置对象创建一个新的连接对象,然后等待 `connect` 事件。
new Connection(config).on('connect', function (err) { });
在事件处理程序中,您可以处理错误并执行 SQL 查询。您可以创建一个代表 SQL 查询的 `Request` 对象,并附加一个回调,该回调将在从数据库中获取结果时执行。
connection.execSql( new Request(sqlQuery, function (err, rowCount, rows) { }) );
请注意,只有当您在作为 `Connection` 参数提供的配置对象中将 `rowCollectionOnRequestCompletion` 设置为 `true` 时,`rows` 参数才能在请求完成后获得(请参阅下面的示例)。
-
在您创建的文件夹中,从命令行运行 `npm install express` 以 安装处理 HTTP 请求的 Express 框架。Express 是一个简单的框架,它在 URL 端点上附加事件处理程序并在某个端口上侦听。
var app = express();
app.get('/version', function (req, res) { });
app.listen(3000);
现在您已准备好开始。您可以使用任何其他框架,但在本示例中,我使用的是 Tedious 和 Express。
演示应用
现在我们已经设置好了应用程序,可以添加一些代码了。如果您接受了所有默认设置,可以将此代码放在 `npm init` 命令生成的 index.js 文件中。
首先,我将配置 Tedious。
var Connection = require('tedious').Connection;
var Request = require('tedious').Request;
var config = {
userName: 'sa',
password: 'pwd',
server: 'localhost',
options: { database: 'AdventureWorks2016CTP3',
rowCollectionOnRequestCompletion : true }
};
配置包括必需的模块,并指定连接配置。唯一的特定参数是 `rowCollectionOnRequestCompletion`。此参数指定行将在 `Request` 构造函数的第二个参数中提供的请求处理程序函数中返回。
注意:Tedious 的默认行为是您需要在每个返回的行上添加事件处理程序。在这种情况下,请求回调中的 `rows` 参数将为 null。在此示例中,我返回一个单元格,因此我希望在 Request 处理程序中获得所有行。然后,我将初始化 Express 应用,初始化它在端口 3000 上侦听,并设置一个侦听 `/version` URL 的处理程序,并创建一个 Tedious 连接。在 `connect` 事件上,连接对象将执行一个自定义的 `sql2http` 函数,该函数在指定的连接(`this` 变量)上执行 SQL 查询,并提供一个 HTTP 响应引用,函数将在此处写入结果。
var express = require('express');
var app = express();
app.get('/version',
function (req, res) {
new Connection(config)
.on( 'connect',
function () {
sql2http(this,
"select COMPRESS(@@VERSION)",
res);
});
});
var server = app.listen(3000);
您可以看到查询很简单——它只是返回存储在 `@@VERSION` 服务器变量中的已压缩的 SQL Server 版本。由于 `COMPRESS` 函数使用 GZip 算法,许多标准应用程序都可以解压缩此消息。
最后,我将需要 `sql2http` 函数,该函数在连接上执行 SQL 查询并将结果发送到 HTTP 请求。
function sql2http(connection, sqlQuery, httpResponse) {
connection.execSql(
new Request(sqlQuery,
function (err, rowCount, rows) {
httpResponse.writeHead(200, {
'Content-Type': 'text/html',
'Content-Encoding': 'gzip'
});
httpResponse.write(rows[0][0].value);
httpResponse.end();
connection.close();
})
); // end execSql
}; // end sql2http
在此,我设置了 `Content-Encoding: gzip`,以通知浏览器响应将以 gzip 格式进行压缩。浏览器将知道内容在显示之前需要解压缩。
此代码仅在连接上执行 SQL 查询,并将列值(第一行/第一列,因为我在 `select COMPRESS(@@VERSION)` 查询中返回了一个标量值)发送到 `httpResponse`。
现在,我们可以使用以下命令从 cmd
提示符启动应用程序。
node index.js
现在,如果我们尝试在浏览器中输入 https://:3000/version,我们将看到已解码的版本。
您可能会注意到,在数据库层中压缩的文本可以在常规 Web 浏览器中成功解压缩并显示在页面上。我不需要任何额外的解压缩层,因为浏览器和 SQL Server 都使用相同的 GZip 算法。
请注意,这是最简单的示例——在实际用例中,您可以压缩表中的一些实际内容,并减少应用程序和 SQL Server 之间的带宽。
主要用例可能是 Ajax 请求,这些请求从 Web 服务器读取格式为 JSON 的数据。如果您想减小客户端(Web 浏览器)和 Web 服务器之间的带宽,您可以在 Web 服务器中 GZip JSON 响应。
作为替代方案,您可以将查询结果格式化为 JSON,并在数据库层中进行压缩。
SELECT COMPRESS (
SELECT *
FROM Sales.SalesOrderHeader
LEFT JOIN Sales.SalesOrderDetail
ON Sales.SalesOrderHeader.SalesOrderID
= Sales.SalesOrderDetail.SalesOrderID
WHERE Sales.SalesOrderHeader.SalesOrderID = @id
FOR JSON AUTO )
内部查询将返回格式化为 JSON 的信息,您需要通过 Ajax 响应返回这些信息。此 JSON 文本可以在数据库层中进行压缩,然后直接发送到 Web 浏览器。
结论
SQL Server 2016 提供了使用标准 GZip 算法压缩和解压缩文本的内置函数。您可以压缩客户端的数据并将其发送到 SQL Server,或者您可以在数据库层压缩响应并将其直接流式传输到客户端。
在此示例中,我有一个 Web 应用程序,它只是将 GZip 压缩的内容直接从数据库流式传输到标准的浏览器,浏览器可以正确地解压数据并显示它。如果您只需要减少数据库层和应用程序层之间的带宽,您可以从 SQL Server 获取压缩数据,然后在应用程序层中解压缩它们。
通过这种方法,您需要在数据库层增加 CPU 周期(因为 SQL Server 需要进行额外的压缩处理)和网络带宽(您可以发送 5-20 倍更少的数据给客户端)之间进行权衡。如果 CPU 使用率不是瓶颈,而网络带宽是您的问题,您可以使用 `COMPRESS` 函数来加速您的应用程序。另一种选择是将原始数据从 SQL Server 返回到 Node.js,并在 Web 应用程序层使用 GZip 压缩。
如果您生成将要返回的内容,GZip 压缩可能会有所帮助,例如,如果您直接在 SQL Server 中将查询结果格式化为 JSON 或 XML,并且想通过某个 Ajax 调用将压缩内容返回给浏览器。