AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / dba / 问题 / 21760
Accepted
ThinkingMonkey
ThinkingMonkey
Asked: 2012-08-01 07:10:17 +0800 CST2012-08-01 07:10:17 +0800 CST 2012-08-01 07:10:17 +0800 CST

PostgreSQL:这是因为锁(行级别)吗?

  • 772

我有一张大约有 210 万个元组的表。其中有纬度和经度列。我正在尝试将其转换为地理类型(带有 SRID 的点)。

我写的函数(过程)在我限制条目时工作正常(比如 : SELECT id,longitude,latitude FROM list_of_location limit 50)。

CREATE OR REPLACE FUNCTION convertlatlon() RETURNS VOID AS $$
DECLARE rec RECORD;
BEGIN
    FOR rec IN SELECT id,longitude,latitude FROM list_of_location
    LOOP
    UPDATE list_of_location SET location= concat('SRID=4326;POINT(',rec.longitude,' ',rec.latitude,')') WHERE id=rec.id;    
    END LOOP;
END;
$$ LANGUAGE 'plpgsql' ;

  • 当我尝试在整个表上运行它时,PostgreSQL 似乎什么都不做。已经等了一个半小时。
  • 在其运行的核心上消耗 99% 的 CPU。
  • 不会启动任何其他 PostgreSQL 实例来利用其他核心(因为请求来自单个用户?)。
  • 这是因为锁(行级别)吗?
  • 如何规避这个?
postgresql spatial
  • 2 2 个回答
  • 346 Views

2 个回答

  • Voted
  1. Best Answer
    a_horse_with_no_name
    2012-08-01T07:48:53+08:002012-08-01T07:48:53+08:00

    在循环内运行 DML 语句从来都不是一个好主意。您正在成倍增加要完成的工作量。关系数据库在对集合进行操作时是最好的,当您执行循环时,您一次只对一行进行操作。

    您可以通过在单个语句中执行更新来实现相同的目的:

    UPDATE list_of_location
       SET location = ST_MakePoint(longitude,latitude)::geography;
    

    我不是 100% 了解计算实际点的语法,因为我不使用几何学的东西,但我想你会明白的。

    • 6
  2. francs
    2012-08-01T23:36:41+08:002012-08-01T23:36:41+08:00

    我建议你不要只在一个函数中完成所有工作,因为函数是 PostgreSQL 中的事务,全部完成或全部不完成!如果表很大,你可能需要花费很多时间来完成这项工作,并且在过程中,表的整行都被锁定(row level lock)。

    所以我建议采用下面的方法,我们可以每隔1000或10000行做一次,这样我们就不需要锁住表的整行(行级锁),而且对生产数据库的影响很小。

    --1 创建tmp表

    create table tmp_location  as select id,longitude,latitude FROM list_of_location;
    
    alter table tmp_location add column flag char(1);
    alter table tmp_location add primary key (id);
    create index idx_tmp_location_flag on tmp_location using btree (flag);
    

    --2 创建函数

    CREATE OR REPLACE FUNCTION convertlatlon() RETURNS VOID AS $$
    DECLARE rec RECORD;
    BEGIN
        FOR rec IN SELECT ( id,longitude,latitude FROM tmp_location where flag is null limit 1000 )
    
        LOOP
          UPDATE list_of_location SET location= concat('SRID=4326;POINT(',rec.longitude,' ',rec.latitude,')') WHERE id=rec.id;    
        END LOOP;
    
        --update flag ,so you can see the  progress of the job
          update tmp_location set flag='Y' where id=rec.id;
    
    END;
    $$ LANGUAGE 'plpgsql' ;
    
    From this way ,we commit the job every 1000 rows,and you also can see the process 
    

    通过查询表tmp_location。

    --3 vi func_file.sql

    \timing
    select convertlatlon();
    select convertlatlon();
    ..
    ..
    ..
    select convertlatlon();
    

    如果表中有 200 万行,你需要写很多行的“select convertlatlon();”,所以你应该在文件 func_file.sql 中写 2000 (2000000/1000) 行

    - -4 执行函数

    --vi 1.sh

    #!/bin/bash
    
    if [ $# != 1 ]; then
    echo Usage: ./1.sh arg1
    echo   Examples:
    echo   1. To run session_wait.sql, enter:
    echo '     1.sh  session_wait >session_wait.out'
    exit 0
    fi
    
    psql -h 127.0.0.1 -d db_name -U role_name -a -c "\i $1"
    

    - -执行函数

        chmod a+x 1.sh
        nohup 1.sh func_file.sql > func_file.out &
    

    你应该在后台执行作业,因为它需要很多时间。

    • 0

相关问题

  • 我可以在使用数据库后激活 PITR 吗?

  • 运行时间偏移延迟复制的最佳实践

  • 存储过程可以防止 SQL 注入吗?

  • PostgreSQL 中 UniProt 的生物序列

  • PostgreSQL 9.0 Replication 和 Slony-I 有什么区别?

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    如何查看 Oracle 中的数据库列表?

    • 8 个回答
  • Marko Smith

    mysql innodb_buffer_pool_size 应该有多大?

    • 4 个回答
  • Marko Smith

    列出指定表的所有列

    • 5 个回答
  • Marko Smith

    从 .frm 和 .ibd 文件恢复表?

    • 10 个回答
  • Marko Smith

    如何在不修改我自己的 tnsnames.ora 的情况下使用 sqlplus 连接到位于另一台主机上的 Oracle 数据库

    • 4 个回答
  • Marko Smith

    你如何mysqldump特定的表?

    • 4 个回答
  • Marko Smith

    如何选择每组的第一行?

    • 6 个回答
  • Marko Smith

    使用 psql 列出数据库权限

    • 10 个回答
  • Marko Smith

    如何从 PostgreSQL 中的选择查询中将值插入表中?

    • 4 个回答
  • Marko Smith

    如何使用 psql 列出所有数据库和表?

    • 7 个回答
  • Martin Hope
    Mike Walsh 为什么事务日志不断增长或空间不足? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland 列出指定表的所有列 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney MySQL 能否合理地对数十亿行执行查询? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx 如何监控大型 .sql 文件的导入进度? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison 你如何mysqldump特定的表? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    pedrosanta 使用 psql 列出数据库权限 2011-08-04 11:01:21 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 对 SQL 查询进行计时? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas 如何从 PostgreSQL 中的选择查询中将值插入表中? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 列出所有数据库和表? 2011-02-18 00:45:49 +0800 CST
  • Martin Hope
    bernd_k 什么时候应该使用唯一约束而不是唯一索引? 2011-01-05 02:32:27 +0800 CST

热门标签

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve