问题
Let's say I have a table in Oracle 12c with columns:
create table t1 (
a number (5,0),
b varchar (5,0)
d ...
e ...
);
Then I insert 100,000,000 records in both columns which have the same values - e.g.
20151 and '20152' ... (for a first record)
20152 and '20152' ... (for a second record)
20153 and '20153' ... (for a third record)
...
Then I add index 1 on column 'a'
and index 2 on column 'b'.
Question is - would the query perform equally fast when executing against column 'a'
as on column 'b'
(e.g. join
query with other table based on a column 'a'
or based on a column 'b'
or WHERE
clause on either of columns)?
Also - would using index on a 'varchar
' column - use more CPU than using index on a 'number' column?
Thanks.
回答1:
[TL;DR] Use dates to store dates, numbers to store numbers and strings to store strings.
How about resource usage?
Oracle stores the NUMBER
data type as 1 byte per 2 digits.
Oracle stores the CHAR
data type as 1 byte per ASCII character (UTF-8 and other encodings may take more for characters in extended sets) and will right-pad the string with space characters so the strings are all exactly the same length.
Oracle stores the VARCHAR2
data type as 1 byte per ASCII character plus a small overhead (1 or 2 bytes) for the string length.
Oracle stores the DATE
data type as 7 bytes (2 for year and 1 for each of month, day, hour, minute, second).
Based on your previous question you appear to be storing year
and quarter
and assuming that you are always going to have 4-digit years and 1-digit quarters then:
NUMBER(5,0)
would take 3 bytes;CHAR(5 CHARACTER)
would take 5 bytes;VARCHAR2(5 CHARACTER)
would take 6 bytes; andDATE
would take 7 bytes.
So only considering memory a NUMBER(5,0)
would be the most efficient.
However
As soon as you start to do arithmetic on year/quarters stored as numbers/strings then you get into performance issues:
For example, getting the next quarter :
- If
quarter
is aNUMBER
data type then you could use:CASE WHEN MOD(quarter,10) = 4 THEN quarter + 7 ELSE quarter + 1 END
but this doesn't handle when you want to add 5 quarters or start subtracting quarters and then the logic starts to get much more complicated. - If
quarter
is aCHAR
data type then you could convert it to a number or a date and use either of those methods (string manipulation is not likely to be performant). - If
quarter
is aDATE
then you just need to useADD_MONTHS( quarter, 3 )
.
The DATE
method is self-documenting and already exists whereas the NUMBER
method would just become a custom function for your approximation of a QUARTER
data type and once you implement all the comparison and manipulation functions you need you will have effectively rewritten the DATE
data type as a UDT for quarters and those functions will be less perfomant than the optimised date functions.
Don't use inappropriate data types - just store dates as dates; numbers as numbers; and strings as string.
来源:https://stackoverflow.com/questions/47043564/oracle-12c-how-much-does-it-really-affect-varchar-column-comparing-to-number-c