处理大数据类型
二进制类型
Vastbase E100提供两种不同的方法存储二进制数据。二进制数据可以使用二进制数据类型BYTEA存储在表中,或者使用大对象特性以一种特殊的格式将二进制数据存储在一个独立的表中,然后通过在表中保存一个类型为 OID 的值来引用该表。
为了判断哪种方法比较合适,必须理解每种方法的局限。 BYTEA数据类型并不适合存储非常大数量的二进制数据。虽然类型为 BYTEA的字段可以存储最多 1G 字节的二进制数据,但是这样它会要求巨大的内存(RAM)来处理这样巨大的数据。用于存储二进制数据的大对象方法更适合存储非常大的数据,但也有自己的局限,具体来说,删除一个引用大数据的行时并不会删除大对象,删除大对象需要单独操作。大对象还有一些安全性的问题,因为连接到数据库的任何用户都可以查看或修改任何大对象,即使他们没有权限查看或修改包含大对象引用的行。
BYTEA
使用BYTEA类型存储二进制数据,可以用getBytes(),setBytes(),getBinaryStream(),setBinaryStream() 进行读写。
例如:
CREATE TABLE images (imgname text, img bytea);
插入记录
File file = new File("myimage.gif");
FileInputStream fis = new FileInputStream(file);
PreparedStatement ps = conn.prepareStatement("INSERT INTO images VALUES (?, ?)");
ps.setString(1, file.getName());
ps.setBinaryStream(2, fis, (int)file.length());
ps.executeUpdate();
ps.close();
fis.close();
在这里,setBinaryStream()将一组字节从流传输到BYTEA类型的列中。setBinaryStream的长度参数必须正确。如果数据已经在byte[]中,那么也可以使用setBytes()方法来实现数据写入。
读取记录
PreparedStatement ps = conn.prepareStatement("SELECT img FROM images WHERE imgname = ?");
ps.setString(1, "myimage.gif");
ResultSet rs = ps.executeQuery();
while (rs.next())
{
byte[] imgBytes = rs.getBytes(1);
// use the data in some way here
}
rs.close();
ps.close();
在这里,二进制数据被读取为byte[]。也可以调用getBinaryStream()处理 。
BLOB
使用BLOB类型存储二进制数据,可以用getBytes(),setBytes(),getBinaryStream(),setBinaryStream()进行读写。
例如:
CREATE TABLE images (uid integer, blob_text blob);
插入记录
File file = new File("myimage.gif");
FileInputStream fis = new FileInputStream(file);
PreparedStatement ps = conn.prepareStatement("INSERT INTO t_user VALUES (?, empty_blob())");
ps.setString(1, 1);
ps.setBinaryStream(2, fis, (int)file.length());
ps.executeUpdate();
ps.close();
fis.close();
在这里,setBinaryStream()将一组字节从流传输到Blob类型的列中。setBinaryStream的长度参数必须正确。如果数据已经在byte[]中,那么也可以使用setBytes()方法来实现数据写入。
读取记录
PreparedStatement ps = conn.prepareStatement("SELECT blob_text FROM t_user WHERE uid= ?");
ps.setString(1, 1);
ResultSet rs = ps.executeQuery();
while (rs.next())
{
Blob blob = rs.getBlob(“blob_text”);
InputStream in = blob.getBinaryStream();
byte[] buff = new byte[1024];
in.read(buff);
// use the data in some way here
In.close();
}
rs.close();
ps.close();
在这里,二进制数据被读取为byte[],也可以使用getBytes()来实现。
CLOB
使用CLOB类型存储二进制数据,可以用getCharacterStream(),setCharatcerStream()进行读写。
例如:
CREATE TABLE images (uid integer, clob_text clob);
插入记录
String data = “123abc一二三”;
PreparedStatement ps = conn.prepareStatement("INSERT INTO t_user VALUES (?, ?)");
ps.setInt(1,1);
StringReader reader = new StringReader(data);
ps.setCharacterStream(2,reader,data.length())
ps.executeUpdate();
reader.close();
ps.close();
在这里,setCharacterStream()获取到字符流写入器。writer将数据写入到字符流中进行输出。
读取记录
PreparedStatement ps = conn.prepareStatement("SELECT clob_text FROM t_user WHERE uid= ?");
ps.setString(1, 1);
ResultSet rs = ps.executeQuery();
while (rs.next())
{
Clob clob = rs.getClob(“clob_text”);
Reader rd = clob.getCharacterStream();
char[] str = new char[1024];
while (true) {
Int i = rd.read(str);
// use the data in some way here
}
}
rs.close();
ps.close();
在这里,二进制数据被读取为char[]。
大对象功能
使用大对象功能存储二进制数据,可以用getBLOB(),setBLOB()进行读写。
例如:
CREATE TABLE imageslo (imgname text, imgoid oid);
插入记录
// All LargeObject API calls must be within a transaction block
conn.setAutoCommit(false);
// Get the Large Object Manager to perform operations with
LargeObjectManager lobj = conn.unwrap(org.postgresql.PGConnection.class).getLargeObjectAPI();
// Create a new large object
long oid = lobj.createLO(LargeObjectManager.READ | LargeObjectManager.WRITE);
// Open the large object for writing
LargeObject obj = lobj.open(oid, LargeObjectManager.WRITE);
// Now open the file
File file = new File("myimage.gif");
FileInputStream fis = new FileInputStream(file);
// Copy the data from the file to the large object
byte buf[] = new byte[2048];
int s, tl = 0;
while ((s = fis.read(buf, 0, 2048)) > 0)
{
obj.write(buf, 0, s);
tl += s;
}
// Close the large object
obj.close();
// Now insert the row into imageslo
PreparedStatement ps = conn.prepareStatement("INSERT INTO imageslo VALUES (?, ?)");
ps.setString(1, file.getName());
ps.setLong(2, oid);
ps.executeUpdate();
ps.close();
fis.close();
// Finally, commit the transaction.
conn.commit();
读取记录
// All LargeObject API calls must be within a transaction block
conn.setAutoCommit(false);
// Get the Large Object Manager to perform operations with
LargeObjectManager lobj = conn.unwrap(org.postgresql.PGConnection.class).getLargeObjectAPI();
PreparedStatement ps = conn.prepareStatement("SELECT imgoid FROM imageslo WHERE imgname = ?");
ps.setString(1, "myimage.gif");
ResultSet rs = ps.executeQuery();
while (rs.next())
{
// Open the large object for reading
long oid = rs.getLong(1);
LargeObject obj = lobj.open(oid, LargeObjectManager.READ);
// Read the data
byte buf[] = new byte[obj.size()];
obj.read(buf, 0, obj.size());
// Do something with the data read here
// Close the object
obj.close();
}
rs.close();
ps.close();
// Finally, commit the transaction.
conn.commit();
字符串类型
VastbaseE100中TEXT类型与VARCHAR类型都是可变长的字符串类型,区别在于VARCHAR类型通过VARCHAR(n)中的n来限制最大长度,而TEXT类型没有。TEXT类型与VARCHAR类型几乎没有性能差别,TEXT类型最多可存储1G数据。
使用TEXT类型存储数据时,可用getString(),getCharacterStream(),setString(), setCharacterStream()来进行读写。
例如:
CREATE TABLE images (id int, msg text);
插入记录
File file = new File("myimage.gif");
Reader reader = new InputStreamReader(new FileInputStream(file));
PreparedStatement ps = conn.prepareStatement("INSERT INTO images VALUES (?, ?)");
ps.setString(1, 12);
ps.setCharacterStream (2, reader);
ps.executeUpdate();
ps.close();
fis.close();
如果数据内容已经在String中,那么也可以使用setString()方法来实现数据写入。
读取记录
PreparedStatement ps = conn.prepareStatement("SELECT msg FROM images WHERE id= ?");
ps.setString(1, 12);
ResultSet rs = ps.executeQuery();
while (rs.next())
{
String imgBytes = rs.getString(1);
// use the data in some way here
}
rs.close();
ps.close();
在这里,TEXT数据被读取为String,也可以调用getCharacterStream()处理 。