PostgreSQL:UPDATE大表

时间:2019-03-29 12:07:38

标签: postgresql sql-update geometry postgis

我有一个2900万行的大型PostgreSQL表。大小(根据pgAdmin中的“统计信息”标签,大小约为9GB。)该表已过gis启用,并带有空的几何列。

我想使用ST_GeomFromText更新几何列,从存储在同一表中的X和Y坐标列(SRID:27700)读取。但是,一次在整个表上运行此查询会导致“磁盘空间不足”和“服务器连接丢失”错误……后者的发生频率较低。

要克服这个问题,我应该分批更新2900万行吗?我该如何做一百万行(第一百万行),然后再进行下一百万行,直到达到2900万?

或者还有其他更有效的方式来更新大型表吗?

我应该添加,该表托管在AWS中。

我的UPDATE查询是:

UPDATE schema.table
SET geom = ST_GeomFromText('POINT(' || eastingcolumn || ' ' || northingcolumn || ')',27700);

2 个答案:

答案 0 :(得分:1)

您没有提供任何服务器规格,在最近的硬件上写入9GB可能非常快。

您应该可以进行一次长时间的更新-除非您同时写入该表。

克服此问题(一个很长的事务,锁定对表的写操作)的一个常见技巧是将UPDATE根据主键划分为多个范围,并在单独的事务中运行。

/* Use PK or any attribute with a known distribution pattern */
UPDATE schema.table SET ... WHERE id BETWEEN 0 AND 1000000;
UPDATE schema.table SET ... WHERE id BETWEEN 1000001 AND 2000000;

对于高水平的并发写入,人们使用更多细微的技巧(例如:SELECT FOR UPDATE / NOWAIT,轻量级锁,重试逻辑等)。

答案 1 :(得分:0)

从我的原始问题开始:

  

但是,立即在整个表上运行此查询会导致“磁盘空间不足”和“与服务器的连接丢失”错误……后者的发生频率较低。

证明我们的Amazon AWS实例数据库空间不足,使我原来的ST_GeomFromText查询无法完成。释放空间将其修复。

重要的是,正如@mlinth所建议的那样,ST_Point运行我的查询要比ST_GeomFromText快得多(24分钟对2小时)。

我最后的查询是:

package com.example.rami_.esmatsongs;

import android.content.Intent;
import android.net.Uri;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.design.widget.BottomNavigationView;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.MenuItem;
import android.view.View;
import android.widget.ImageView;

import com.theartofdev.edmodo.cropper.CropImage;

public class MainActivity extends AppCompatActivity {

    private BottomNavigationView mainbottomNav;
    private HomeFragment homeFragment;
    private NotificationFragment notificationFragment;
    private AccountFragment accountFragment;
    private AboutFragment aboutFragment;
    private Uri mCropImageUri;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // FRAGMENTS
        homeFragment = new HomeFragment();
        notificationFragment = new NotificationFragment();
        accountFragment = new AccountFragment();
        aboutFragment = new AboutFragment();
        initializeFragment();
        mainbottomNav = (BottomNavigationView) findViewById(R.id.mainBottomNav);
        mainbottomNav.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {
            @Override
            public boolean onNavigationItemSelected(@NonNull MenuItem item) {

                switch (item.getItemId()) {
                    case R.id.home_bottom:
                        replaceFragment(homeFragment);
                        return true;

                    case R.id.account_bottom:
                        replaceFragment(accountFragment);
                        return true;

                    case R.id.notification_bottom:
                        replaceFragment(notificationFragment);
                        return true;

                    case R.id.about_bottom:
                        replaceFragment(aboutFragment);
                        return true;

                    default:
                        return false;
                }
            }
        });
    }

    private void initializeFragment() {

        FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();

        fragmentTransaction.add(R.id.main_container, homeFragment);
        fragmentTransaction.add(R.id.main_container, notificationFragment);
        fragmentTransaction.add(R.id.main_container, accountFragment);
        fragmentTransaction.add(R.id.main_container, aboutFragment);
        fragmentTransaction.hide(notificationFragment);
        fragmentTransaction.hide(accountFragment);
        fragmentTransaction.hide(aboutFragment);

        fragmentTransaction.commit();

    }


    private void replaceFragment(Fragment fragment) {

        FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
        if (fragment == homeFragment) {
            fragmentTransaction.hide(notificationFragment);
            fragmentTransaction.hide(accountFragment);
            fragmentTransaction.hide(aboutFragment);
        }

        if (fragment == accountFragment) {
            fragmentTransaction.hide(homeFragment);
            fragmentTransaction.hide(notificationFragment);
            fragmentTransaction.hide(aboutFragment);
        }

        if (fragment == notificationFragment) {
            fragmentTransaction.hide(homeFragment);
            fragmentTransaction.hide(accountFragment);
            fragmentTransaction.hide(aboutFragment);
        }

        if (fragment == aboutFragment) {
            fragmentTransaction.hide(homeFragment);
            fragmentTransaction.hide(accountFragment);
            fragmentTransaction.hide(notificationFragment);
        }

        fragmentTransaction.show(fragment);
        //fragmentTransaction.replace(R.id.main_container, fragment);
        fragmentTransaction.commit();
    }
}

    enter code here