我是一名学生,现在我遇到了一个我自己无法解决的问题(在互联网上搜索后)。
\n我不会给出我的 \xc2\xabhomework\xc2\xbb 因为我想了解我在做什么,但我会使用一个例子。
\n我有以下图表:\n
以及以下内容:
\nEmployee( ID,DepartamentID,Floor)
\n外键( DepartamentID, Floor) 引用Departament(DepartamentID,Floor)
部门( DepartamentID, Floor, 话务员)
\n外键话务员引用 Employee(ID)
因此,根据本指南,我的实际 SQL 代码是:
\nCREATE TABLE Employee(\n ID varchar(25) not null,\n DepartamentID varchar(25),\n Floor varchar(25),\n CONSTRAINT pk_ID PRIMARY KEY (ID),\n) ENGINE=InnoDB;\n\nCREATE TABLE Departament(\n DepartamentID varchar(25) not null,\n Floor varchar(25) not null,\n Attendant varchar(25) not null,\n CONSTRAINT pk_dept PRIMARY KEY (DepartamentID, Floor),\n CONSTRAINT fk_att FOREIGN KEY (Attendant) REFERENCES Employee (ID),\n) ENGINE=InnoDB;\n\nALTER …Run Code Online (Sandbox Code Playgroud) 我们目前正在尝试将大量数据(大约 2700 万条记录、200 列)插入到 postgres 9.4 数据库的单个表中。(是的,最好将表重构为较小的表,但首先尝试此方法)
插入由 libpq 应用程序管理,该应用程序使用“INSERT INTO ...”一次插入大约 300 行数据。我们已经阅读过有关使用 COPY 命令的信息,但就我们当前的使用情况而言,前者是更好的选择,具有不错的性能。有些列是数组,可能相当大,但使用此设置,我们可以毫无问题地插入大约 1000 万行数据。
问题:每当表达到大约 600GB(约 2000 万行)时,插入就会停止。pg_stat_activity 显示插入查询处于活动状态,并且输出和日志中都没有错误。对于通常需要几秒钟的插入查询,我们已经等待了超过 12 个小时。
我们尝试了一些方法,例如删除唯一索引(主键)、运行 ANALYZE 以及重新启动插入,但每当表达到 600GB 左右时,插入就会停止。我们不相信我们会遇到任何接近表格最大尺寸的情况,因此不确定发生了什么。
有人有什么主意吗?或者对如何找出插入过程中出现的问题有一些建议?
谢谢!
更新#1:如上所述,插入的行有 200 列宽,其中一些字段是数组。
当对表的插入停止时,我们尝试手动插入记录:
正如我们之前所见,典型的行不会被插入,查询也会挂起。当我们减少填充列的数量(例如,插入仅包含 200 个值中的 30 个值的记录)时,插入会成功,没有延迟/减慢。通过改变查询中填充列的数量,我们发现了一个截止点,如果插入的列数大于一定数量,则插入将挂起。(我们也尝试了不同的列组合,但没有任何效果)
我们不知道如何直接解决这个问题,因此我们目前正在按照建议将数据分区到不同的(较小的)表中。然而,任何文档中都没有提到这个问题,所以任何建议仍然将不胜感激!
我有一个 PostgreSQL 数据库,其中有很多相同结构的表,总共 36 列:
CREATE TABLE some_schema.some_table (
id integer NOT NULL DEFAULT nextval('some_schema.id_seq'::regclass),
col2,
col3,
col4,
[...],
col35,
mi_prinx integer NOT NULL DEFAULT nextval('some_schema.mi_prinx_seq'::regclass),
CONSTRAINT some_table_pkey PRIMARY KEY (mi_prinx)
)
Run Code Online (Sandbox Code Playgroud)
在许多情况下,我必须从具有相同结构的另一个表中插入记录:
INSERT INTO some_schema.some_table (col2,col3...col35)
SELECT col2,col3...col35
FROM some_schema.another_table_with_same_structure;
Run Code Online (Sandbox Code Playgroud)
有没有一种方法可以做到这一点,而不必列出所有没有默认值的列?我想我可以以某种方式使用,但我无法根据文档DEFAULT VALUES获得正确的语法。
我有两个表和一个触发器,并且正在ProjectsTable像这样插入值:
CREATE TABLE ProjectsTable
(
ProjectID NUMBER(6) NOT NULL,
ProjectName VARCHAR2(200) NOT NULL,
Cost NUMBER(10,2),
ExpenseTotal NUMBER(10,2),
CostRemaining NUMBER(10,2),
PRIMARY KEY (ProjectID)
);
CREATE TABLE ExpenseTable
(
ID NUMBER(6) NOT NULL,
ProjectID NUMBER(6) NOT NULL,
ExpenseAmount NUMBER(10,2),
ExpenseDate NUMBER(4),
CONSTRAINT fk
FOREIGN KEY (ProjectID)
REFERENCES ProjectsTable(ProjectID)
);
CREATE TRIGGER ExpenseSum AFTER INSERT ON ExpenseTable FOR EACH ROW
BEGIN
UPDATE ProjectsTable P
SET ExpenseTotal =
(SELECT SUM(ExpenseAmount) from ExpenseTable
where ExpenseTable.ProjectID= P.ProjectID)
where P.ProjectID = :New.ProjectID;
END;
/
INSERT …Run Code Online (Sandbox Code Playgroud) 以下是同一事物的两种不同语法。
带有COPY TABLE AS SELECT( CTAS)。
CREATE TABLE main
AS
SELECT *
FROM other;
Run Code Online (Sandbox Code Playgroud)作为单独的语句CREATE TABLE和INSERT INTO
CREATE TABLE main (like other);
INSERT INTO main
SELECT *
FROM other;
Run Code Online (Sandbox Code Playgroud)我观察到的CTAS比明显快CREATE TABLE.. INSERT。第一个需要 20 秒才能完成执行。第二个语法二需要 1 分 15 秒才能完成执行。
差异的原因可能是什么?
我正在开发一个数据仓库。我们每晚刷新的一个临时表有大约 1000 万行。我们正在使用自定义构建的 ETL 工具,我无法对其进行太多更改。该工具像这样加载这个临时表:
truncate stage_table;
insert into stage_table with (tablockx) (column1, column2, etc...)
exec load_stage_table @batch_id = @batch_input
Run Code Online (Sandbox Code Playgroud)
的内容load_stage_table有一些设置和选择语句。我无法分享确切的代码,但这是一个基本示例。
create table load_stage_table
(
@batch_id varchar(max) = null
)
as
-- <update batch_id in batch_table>
-- collect data
select
column1 = table1.column1,
column2 = table2.column2,
...
from table1
join table2
on table2.id = table1.table2_id
-- many more similar joins
Run Code Online (Sandbox Code Playgroud)
问题是,当我按照 ETL 工具运行的方式运行存储过程时,运行时间几乎是 30 分钟。但是,如果我修改存储过程以在内部包含插入语句,则只需 1 分钟。
create table load_stage_table
(
@batch_id varchar(max) = null
)
as
-- …Run Code Online (Sandbox Code Playgroud) performance sql-server insert sql-server-2016 exec query-performance
我有一个dbo.Groups定义如下的表:
CREATE TABLE dbo.Groups
(
GroupID int NOT NULL IDENTITY (1,1) PRIMARY KEY
);
Run Code Online (Sandbox Code Playgroud)
该表实际上只包含一IDENTITY列。
有时我想一次插入多行并获取生成的 ID。(我已经有一个预定义的表变量,@output其中包含ID要在OUTPUT子句中使用的单个列。)
现在我知道如果它是单行我将如何进行:
INSERT INTO
dbo.GroupID
OUTPUT
inserted.GroupID INTO @output (ID)
DEFAULT VALUES
;
Run Code Online (Sandbox Code Playgroud)
但我希望能够一次性插入两个或更多。实际数量由此查询返回的行数决定:
SELECT
*
FROM
dbo.MySource
;
Run Code Online (Sandbox Code Playgroud)
因此,如果查询返回一行,我想插入一行dbo.Groups并返回生成的GroupID. 如果它是一百行,那么我希望插入一百行并同时生成和返回一百个 ID。
一种明显的方法是在循环中一次插入一行。我想避免这种情况,而是使用基于集合的方法,类似于
INSERT INTO
dbo.GroupID
OUTPUT
inserted.GroupID INTO @output (ID)
SELECT
... -- what?
FROM
dbo.MySource
;
Run Code Online (Sandbox Code Playgroud)
有没有办法IDENTITY在(最好)单个语句中只用一列将多行插入到表中?
我正在使用 PostgreSQL 11。我想有条件地将值插入表中,同时插入的结果包括null未导致插入的输入的每一行。
例如
CREATE TABLE all_sums (sum INTEGER);
SELECT
CASE WHEN a_sum IS NULL THEN null
ELSE (SELECT sum FROM (INSERT INTO sums (sum) VALUES (sum) RETURNING sum))
END
FROM
(SELECT a + b FROM (VALUES (1, null), (null, 2), (2, 3)) AS row (a, b))
AS a_sum;
Run Code Online (Sandbox Code Playgroud)
应该导致表格all_sums看起来像:
all_sums: sum
------
5
(1 row)
Run Code Online (Sandbox Code Playgroud)
但查询的输出应该是:
null
null
5
------
(3 rows)
Run Code Online (Sandbox Code Playgroud)
此示例因语法错误而失败:
ERROR: syntax error at or near "INTO"
Run Code Online (Sandbox Code Playgroud)
有什么方法可以实现所需的查询输出?
(对于上下文:我这样做的原因是因为还有进一步的查询依赖于知道插入是否发生在特定行上。
这是通过将我的查询从每行一个转换为每列一个来更有效地从文件中插入一些数据的努力的一部分。不过,我不是在寻找其他提高插入速度的技巧,如果不可能,我很高兴在这一点上结束。)
想象一下具有 1:M 关系的多个父子表。我想“级联” - 根据根父表行选择插入重复行。每个表都有IDENTITY主键,每个子表都有其父 ID 的 FK(上一级)。
给定根父表 ID,为其及其所有子表插入重复行。
我尝试了“级联”插入 CTE,但遇到了RETURNING仅限返回插入数据的问题,而我需要额外的信息来连接下一个INSERT.
我通过添加额外的列 ( ) 来完成此任务copied_from_id。
有没有办法在没有额外列的情况下完成相同的任务?
我确实看到了@Erwin Brandstetter 的这个答案,但他的例子只有 1 个父母和孩子,我不知道如何将其扩展到多个级别
这是示例 DDL 和 DML 来说明问题
--DROP TABLE IF EXISTS lvl_one,lvl_two,lvl_three CASCADE;
CREATE TABLE IF NOT EXISTS public.lvl_one (
id bigint NOT NULL GENERATED ALWAYS AS IDENTITY,
name text,
CONSTRAINT lvl_one_pk …Run Code Online (Sandbox Code Playgroud) 我使用 PostgreSQL 13(最新的 dockerized)进行了简单的设置:
CREATE TABLE stop (
id INT UNIQUE,
name TEXT,
PRIMARY KEY(id)
);
CREATE TABLE line (
id INT UNIQUE,
name TEXT,
PRIMARY KEY(id)
);
CREATE TABLE line_stops_sequence(
id SERIAL PRIMARY KEY,
line INT,
stop INT,
CONSTRAINT fk_line FOREIGN KEY(line) REFERENCES line(id),
CONSTRAINT fk_stop FOREIGN KEY(stop) REFERENCES stop(id)
);
Run Code Online (Sandbox Code Playgroud)
当我启动下面这句话时
INSERT INTO line(id, name) VALUES (1, 'Line 1');
INSERT INTO stop(id, name) VALUES (2, 'Stop 2');
INSERT INTO line_stops_sequence(line, stop) VALUES (1,1), (1,2) ON CONFLICT ON CONSTRAINT …Run Code Online (Sandbox Code Playgroud) insert ×10
postgresql ×6
bulk-insert ×2
constraint ×2
sql-server ×2
subquery ×2
case ×1
ctas ×1
cte ×1
errors ×1
exec ×1
foreign-key ×1
identity ×1
mysql ×1
oracle ×1
oracle-11g ×1
performance ×1
trigger ×1