我正在處理大量非常簡單的資料(點云)。我想使用 Python 將這些資料插入到 Postgresql 資料庫中的一個簡單表中。
我需要執行的插入陳述句示例如下:
INSERT INTO points_postgis (id_scan, scandist, pt) VALUES (1, 32.656, **ST_MakePoint**(1.1, 2.2, 3.3));
請注意 INSERT 陳述句中對 Postgresql 函式 ST_MakePoint 的呼叫。
我必須呼叫數十億次(是的,數十億次),所以顯然我必須以更優化的方式將資料插入 Postgresql。有許多策略可以批量插入資料,因為本文以非常好的和資訊豐富的方式(insertmany、復制等)介紹了這些策略。 https://hakibenita.com/fast-load-data-python-postgresql
但是沒有示例顯示當您需要在服務器端呼叫函式時如何進行這些插入。我的問題是:當我需要使用 psycopg 在 Postgresql 資料庫的服務器端呼叫函式時,如何批量插入資料?
任何幫助是極大的贊賞!謝謝!
請注意,使用 CSV 沒有多大意義,因為我的資料很大。或者,我已經嘗試用 ST_MakePoint 函式的 3 個輸入的簡單列填充臨時表,然后,在所有資料都進入這個臨時函式之后,呼叫 INSERT/SELECT。問題是這需要很多時間,而且我需要的磁盤空間量是荒謬的。
uj5u.com熱心網友回復:
最重要的是,為了在合理的時間內以最小的努力做到這一點,是將這個任務分解成組件,以便您可以分別利用不同的 Postgres 功能。
首先,您需要先創建表格減去幾何變換。如:
create table temp_table (
id_scan bigint,
scandist numeric,
pt_1 numeric,
pt_2 numeric,
pt_3 numeric
);
由于我們不添加任何索引和約束,這很可能是將“原始”資料匯入 RDBMS 的最快方式。
最好的方法是使用 COPY 方法,您可以直接從 Postgres 使用該方法(如果您有足夠的訪問權限),也可以通過 Python 介面使用https://www.psycopg.org/docs/cursor.html #cursor.copy_expert
這是實作此目的的示例代碼:
iconn_string = "host={0} user={1} dbname={2} password={3} sslmode={4}".format(target_host, target_usr, target_db, target_pw, "require")
iconn = psycopg2.connect(iconn_string)
import_cursor = iconn.cursor()
csv_filename = '/path/to/my_file.csv'
copy_sql = "COPY temp_table (id_scan, scandist, pt_1, pt_2, pt_3) FROM STDIN WITH CSV HEADER DELIMITER ',' QUOTE '\"' ESCAPE '\\' NULL AS 'null'"
with open(csv_filename, mode='r', encoding='utf-8', errors='ignore') as csv_file:
import_cursor.copy_expert(copy_sql, csv_file)
iconn.commit()
下一步將是從現有的原始資料有效地創建您想要的表。然后,您將能夠使用單個 SQL 陳述句創建您的實際目標表,并讓 RDBMS 發揮它的魔力。
一旦資料在 RDBMS 中,稍微優化它并添加一個或兩個索引(如果適用)是有意義的(最好是主索引或唯一索引以加速轉換)
這將取決于您的資料/用例,但這樣的事情應該會有所幫助:
alter table temp_table add primary key (id_scan); --if unique
-- or
create index idx_temp_table_1 on temp_table(id_scan); --if not unique
要將資料從 raw 移動到目標表中:
with temp_t as (
select id_scan, scandist, ST_MakePoint(pt_1, pt_2, pt_3) as pt from temp_table
)
INSERT INTO points_postgis (id_scan, scandist, pt)
SELECT temp_t.id_scan, temp_t.scandist, temp_t.pt
FROM temp_t;
這將一次性從上一個表中選擇所有資料并對其進行轉換。
您可以使用的第二個選項類似。您可以將所有原始資料直接加載到 points_postgis,同時將其分成 3 個臨時列。然后使用alter table points_postgis add column pt geometry;并跟進更新,并洗掉臨時列:update points_postgis set pt = ST_MakePoint(pt_1, pt_2, pt_3);&alter table points_postgis drop column pt_1, drop column pt_2, drop column pt_3;
主要的收獲是,最高效的選擇不是專注于最終的決賽桌狀態,而是將其分解為易于實作的塊。Postgres 將輕松處理數十億行的匯入以及之后的轉換。
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/517010.html
上一篇:當我將db從Heroku匯入本地Postgres時,Heroku存盤latest.dump檔案的位置在哪里?
下一篇:PostgreSQL遞回查找值
