You Asked
We're going to allow sys admins to create columns in the DB using a UI for our applicatoin.
I am wondering if there will be any degradation in performance if say, the Users are allowed to create a 4000 nvarchar irrespective if they use only 4 chars or 4000 chars, everytime they need to create a new String column, they get to create a 4K nvarchar, or would it be more useful to give them a choice of say 4, 40, 400 & 4000 sized String columns?
Is there a performance degradation when reading this data?
Our app will be Java based.
Thanks
and Tom said...
It will affect
o data integrity
o data quality
o data usability
o runtime performance
o memory utilization
in a negative fashion. the funny thing is - we can easily INCREASE the width of a column - it is really hard to fix a column and shrink its width however!!!!
Consider this tiny schema:
drop table t1;
drop table t2;
create table t1 as select * from all_objects;
create table t2
(OWNER varchar2(4000),
OBJECT_NAME varchar2(4000),
SUBOBJECT_NAME varchar2(4000),
OBJECT_ID varchar2(4000),
DATA_OBJECT_ID varchar2(4000),
OBJECT_TYPE varchar2(4000),
CREATED varchar2(4000),
LAST_DDL_TIME varchar2(4000),
TIMESTAMP varchar2(4000),
STATUS varchar2(4000),
TEMPORARY varchar2(4000),
GENERATED varchar2(4000),
SECONDARY varchar2(4000)
)
/
insert into t2 select * from t1;
Ok, we run this java program against it:
public static void process_data( Connection conn, String inputs )
throws Exception
{
PreparedStatement pstmt;
String col;
int i;
pstmt = conn.prepareStatement
("select * from " + inputs );
((OraclePreparedStatement)pstmt).setRowPrefetch(100);
System.out.println("select * from " + inputs );
ResultSet rset = pstmt.executeQuery();
while( rset.next() )
{
for( i = 1; i<=13; i++ )
{
col = rset.getString(i);
}
//System.in.read();
//break;
}
rset.close();
pstmt.close();
}
That is, array fetch 100 rows at a time (good overall fetch size) and look at each column. Just like a program might. Now, t1 and t2 have the *same* data, just t2 is all about varchar2(4000):
[tkyte@xtkyte-pc j]$ time java select t1
select * from t1
real 0m2.124s
user 0m1.590s
sys 0m0.100s
[tkyte@xtkyte-pc j]$ time java select t1
select * from t1
real 0m2.306s
user 0m1.790s
sys 0m0.070s
[tkyte@xtkyte-pc j]$ time java select t2
select * from t2
real 0m5.565s
user 0m5.090s
sys 0m0.120s
[tkyte@xtkyte-pc j]$ time java select t2
select * from t2
real 0m5.560s
user 0m5.040s
sys 0m0.110s
so, to call is slower is an understatement (and bear in mind, we've NEGATIVELY impacted the t1 example by doing the string conversion!!!! This is worse than it looks)
Next, a peek at how this might affect memory (yea of the middle tier persuasion - take note, consider how a couple HUNDRED queries might affect you in the aggregate on the client side....)
I'm "cheating", I'm going to uncomment the read call above and when the java client "hangs", use "$ top" to measure it:
$ java select t1
RSS=19m SIZE=19,596 SHARE=10,520k
$ java select t2
RSS=34m SIZE=39,880k SHARE=10,460k
These numbers were repeated over and over, run after run - think "square array" sum(column*width)*prefetch....
Do NOT use varchar2(4000) for "every column, just in case".
(regardless of language)
Rating
(3 ratings)
Is this answer out of date? If it is, please let us know via a Comment