我有一个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);
答案 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