- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
在我们的网络堆栈中,我正在努力实现一项功能,允许用户基本上指定几个过滤条件(现在称为 list),这些条件是从 Postgres 数据库中的表中获取的.用户可以拥有许多这样的列表,每个列表都具有一组列的条件,例如“包含”或“等于”。
其中涉及的逻辑相对简单,但问题开始是因为客户希望能够每天查看列表查询结果的更改/更新(因此本质上是存储增量的每日快照)和其中一些过滤条件可能很慢并且在非索引列上运行大型表(有问题的表每个有 2-3 百万行)。
目前我们使用 Redis 和 Postgres 作为我们的存储后端,我不完全确定什么是最好的方式来表示甚至管理这些日常更新,以及为每个用户的每个列表索引它们。
我确信很多处理分析数据的软件都解决了类似的问题,但我不太熟悉如何有效地解决这个问题,我不想重新发明轮子,所以我想问一下是否有人对如何实现它有任何想法/建议(可能使用其他软件以及 PG 和 Redis)?
详细来说,必须每 12 小时(目前)对所有现有列表批量执行此操作,最有可能使用调用更新程序的守护程序(或只是一个 cronjob)。
(抱歉,如果这个问题看起来含糊不清,我试图概述我能想到的每一个可能的方面,但我不确定我是否做得足够好)
最佳答案
我们所做的是使用触发器将所有更改存储在审计表中,将表的键存储为文本数组,并将更改的值(旧值和新值)存储为两个 jsonb 字段:
CREATE OR REPLACE FUNCTION text2intsafe(text) RETURNS int AS $$
SELECT CASE WHEN $1 ~ '^ *-?\d{1,9} *$' THEN $1::int END
$$ LANGUAGE SQL IMMUTABLE RETURNS NULL ON NULL INPUT;
CREATE TABLE IF NOT EXISTS crm.audit (
audit_id bigserial NOT NULL PRIMARY KEY,
date timestamptz NOT NULL DEFAULT CURRENT_TIMESTAMP,
username text NOT NULL DEFAULT crm.f_user(),
tableclass regclass NOT NULL,
action text NOT NULL CHECK (action IN ('I','U','D')),
id text[] NOT NULL,
old_data jsonb NULL,
new_data jsonb NULL
);
CREATE INDEX ON audit (date);
CREATE INDEX ON audit (tableclass, id);
CREATE INDEX ON audit USING gin (old_data);
CREATE INDEX audit_tableclass_id_idx ON audit (tableclass, text2intsafe(id[1]));
CREATE OR REPLACE FUNCTION f_audit_get_value(p_tableclass regclass, p_date timestamptz, p_id text[], p_object text[]) RETURNS jsonb AS $$
SELECT COALESCE(
(SELECT a.old_data#>$4
FROM audit a
WHERE a.tableclass = $1 AND a.date >= $2 AND id = $3 AND (a.old_data#>$4) IS NOT NULL
ORDER BY a.date LIMIT 1),
(SELECT a.new_data#>$4
FROM audit a
WHERE a.tableclass = $1 AND a.date < $2 AND id = $3 AND (a.new_data#>$4) IS NOT NULL
ORDER BY a.date DESC LIMIT 1))
$$ LANGUAGE SQL SECURITY DEFINER STABLE STRICT;
CREATE OR REPLACE FUNCTION f_audit_get_text(p_tableclass regclass, p_date timestamptz, p_id text[], p_object text[]) RETURNS text AS $$
SELECT COALESCE(
(SELECT a.old_data#>>$4
FROM audit a
WHERE a.tableclass = $1 AND a.date >= $2 AND id = $3 AND (a.old_data#>$4) IS NOT NULL
ORDER BY a.date LIMIT 1),
(SELECT a.new_data#>>$4
FROM audit a
WHERE a.tableclass = $1 AND a.date < $2 AND id = $3 AND (a.new_data#>$4) IS NOT NULL
ORDER BY a.date DESC LIMIT 1))
$$ LANGUAGE SQL SECURITY DEFINER STABLE STRICT;
CREATE OR REPLACE FUNCTION f_jsonb_diff(jsonb, jsonb) RETURNS jsonb AS $$
-- return an object with attributes from $2 that differ from those of $1
SELECT json_object_agg(v2.key, CASE COALESCE(t2, t1)
WHEN 'object' THEN public.f_json_diff(CASE WHEN t1 IS NULL THEN '{}'::jsonb ELSE v1.value END, CASE WHEN t2 IS NULL THEN '{}'::jsonb ELSE v2.value END)
WHEN 'array' THEN public.f_json_array_diff(CASE WHEN t1 = 'array' THEN v1.value ELSE '[]'::jsonb END, CASE WHEN t2 = 'array' THEN v2.value ELSE '[]'::jsonb END)
ELSE v2.value END)::jsonb
FROM jsonb_each(COALESCE(CASE WHEN jsonb_typeof($2) = 'object' THEN $2 END, '{}'::jsonb)) v2
LEFT JOIN jsonb_each(COALESCE(CASE WHEN jsonb_typeof($1) = 'object' THEN $1 END, '{}'::jsonb)) v1 on (v1.key = v2.key)
LEFT JOIN LATERAL NULLIF(jsonb_typeof(v1.value), 'null') t1 ON (true)
LEFT JOIN LATERAL NULLIF(jsonb_typeof(v2.value), 'null') t2 ON (true)
WHERE v1.value IS DISTINCT FROM v2.value
$$ LANGUAGE sql IMMUTABLE;
CREATE OR REPLACE FUNCTION tf_audit() RETURNS TRIGGER AS $$
DECLARE
_id text[];
_key int2vector;
_orow jsonb;
_nrow jsonb;
_odata jsonb;
_ndata jsonb;
BEGIN
_key := indkey FROM pg_index WHERE indrelid = TG_RELID AND indisunique ORDER BY indisprimary DESC LIMIT 1;
IF TG_OP = 'INSERT' THEN
_ndata := to_jsonb(NEW);
_id := ARRAY(SELECT _ndata->>attname FROM pg_attribute WHERE attrelid = TG_RELID AND attnum = ANY(_key) ORDER BY attnum);
ELSIF TG_OP = 'UPDATE' THEN
_nrow := to_jsonb(NEW);
_orow := to_jsonb(OLD);
_odata := f_jsonb_diff(_nrow, _orow);
_ndata := f_jsonb_diff(_orow, _nrow);
_id := ARRAY(SELECT _nrow->>attname FROM pg_attribute WHERE attrelid = TG_RELID AND attnum = ANY(_key) ORDER BY attnum);
ELSIF TG_OP = 'DELETE' THEN
_odata := to_jsonb(OLD);
_id := ARRAY(SELECT _odata->>attname FROM pg_attribute WHERE attrelid = TG_RELID AND attnum = ANY(_key) ORDER BY attnum);
END IF;
IF _odata <> '{}'::jsonb OR _ndata <> '{}'::jsonb THEN
INSERT INTO audit (username, tableclass, action, id, old_data, new_data)
VALUES (crm.f_user(), TG_RELID, substring(TG_OP FROM 1 FOR 1), _id, _odata, _ndata);
END IF;
RETURN CASE WHEN TG_OP = 'DELETE' THEN OLD ELSE NEW END;
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;
然后对于您要审核的每个表,只需添加:
CREATE TRIGGER t_table_audit BEFORE UPDATE OR DELETE ON table
FOR EACH ROW EXECUTE PROCEDURE crm.tf_audit();
然后,您可以为任何已审计的表(从实现审计之日起)在任意两个时间点之间生成准确的增量。
关于database - 以高效的方式维护和更新大量 SQL 结果子集,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38038976/
我们使用 Azure 弹性池,生成多个客户端数据库和一个引用客户端数据库的主数据库。 我们已经拥有多个数据库,并且正在开发新版本的代码。我们使用 EF6 代码优先。当我们对模型进行更改(添加属性)时,
我们使用 Azure 弹性池,生成多个客户端数据库和一个引用客户端数据库的主数据库。 我们已经拥有多个数据库,并且正在开发新版本的代码。我们使用 EF6 代码优先。当我们对模型进行更改(添加属性)时,
我希望将一些信息分发到不同的机器上,以便在没有任何网络开销的情况下实现高效和极快的访问。数据存在于关系模式中,实体之间的关系是“加入”的要求,但根本不是写入数据库的要求(它会离线生成)。 我非常相信
我使用 GrapheneDB 来托管我的 neo4j 数据库 (db)。 问题 我有 N客户并且正在寻找自动分离他们的内容(他们独特的数据库)的方法,以便: 它不重叠数据 操作速度不受影响。 选项 1
当服务器开始工作(Tomcat)时,日志显示此错误: org.springframework.beans.factory.BeanDefinitionStoreException: Invalid b
我在 Oracle 数据库实例中按以下方式创建了一个触发器。 CREATE OR REPLACE TRIGGER after_logon_on_database AFTER LOGON ON DATA
原谅我的无知,我是数据库约定的初学者。 这是我的 SQLite 代码:(由我的数据库浏览器自动生成) CREATE TABLE `ResearchItems` ( `ID` INTEGER NO
是的是的是的,我已经在整个互联网上搜索过这个问题。一些结果发现,甚至来自 Stackoverflow。但是他们中的大多数人说“你应该自动加载数据库”,或者“parent::__construct();
我正在创建一个 Mac 应用程序,它将一些数据保存到 SQLite 数据库中。问题是:当我关闭数据库并再次打开时,数据不存在了。这是我的代码: NSString *sql = [NSString st
我正在建立一个网站,我打算发布各种帖子,比如教程、文章等。我打算用 php 来管理它,但是当涉及到存储每个帖子的内容时,将要显示的文本,更好的选择是:使用单独的文本文件还是将其添加为数据库中的每个条目
关闭。这个问题需要更多focused .它目前不接受答案。 想改进这个问题吗? 更新问题,使其只关注一个问题 editing this post . 关闭 3 年前。 Improve this qu
对不起,这个关键字对我来说没有任何意义...有人可以给我一个定义吗? 提前致谢... 最佳答案 这是一个品牌。 http://pervasive.com/这是他们的数据库产品的链接 http://ww
我已经在 docker 版本 1.10.1 的 docker 镜像中安装了 PostgreSQL 9.4.6。根据这张官方图片: https://github.com/docker-library/p
当我的 android 应用程序尝试读取 android 短信数据库时,我遇到了这个崩溃。读取android短信数据库的代码类似于下面的代码 fragment : String SMS_URI = "
我有一个 public kit repo,我推送了 v1.0.3 并具有以下结构 go -database --database.go --go.mod --go.sum 我需要它 require g
关闭。这个问题需要更多focused .它目前不接受答案。 想改进这个问题吗? 更新问题,使其只关注一个问题 editing this post . 关闭 9 年前。 Improve this qu
我们正在使用MySQL数据库在Go中创建一个Web应用程序。我们的用户一次只能拥有一个活跃的客户端。就像Spotify一样,您一次只能在一台设备上听音乐。为此,我制作了一个映射,将用户ID和作为其值的
我已经尝试在 PostgreSQL 中创建数据库好几天了,遇到了几个问题,但似乎卡住了。 我在 PostgreSQL 中手动创建了一个名为 postgres_development 的数据库,因为 b
我正在创建一个 iMessage 应用程序,它需要连接到与我的常规应用程序相同的数据库。 我调用 FirebaseApp.configure() 并对用户进行身份验证,但出于某种原因,在所有 Data
就像std::unordered_map但所有数据都应存储在磁盘上而不是内存中。 按照我的理解,应该做两部分:索引和存储。我已经学习了一些关于索引的数据结构,比如 Linear-Hash 或 B-Tr
我是一名优秀的程序员,十分优秀!