Oracle Table structure - oracle

I have a table in Oracle Database which has 60 columns. Following is the table structure.
ID NAME TIMESTAMP PROERTY1 ...... PROPERTY60
This table will have many rows. the size of the table will be in GBs. But the problem with the table structure is that in future if I have to add a new property, I have to change the schema. To avoid that I want to change the table structure to following.
ID NAME TIMESTAMP PROPERTYNAME PROPERTYVALUE
A sample row will be.
1 xyz 40560 PROPERTY1 34500
In this way I will be able to solve the issue but the size of the table will grow bigger. Will it have any impact on performance in terms on fetching data. I am new to Oracle. I need your suggestion on this.

if I have to add a new property, I have to change the schema
Is that actually a problem? Adding a column has gotten cheaper and more convenient in newer versions of Oracle.
But if you still need to make your system dynamic, in a sense that you don't have to execute DDL for new properties, the following simple EAV implementation would probably be a good start:
CREATE TABLE FOO (
FOO_ID INT PRIMARY KEY
-- Other fields...
);
CREATE TABLE FOO_PROPERTY (
FOO_ID INT REFERENCES FOO (FOO_ID),
NAME VARCHAR(50),
VALUE VARCHAR(50) NOT NULL,
CONSTRAINT FOO_PROPERTY_PK PRIMARY KEY (FOO_ID, NAME)
) ORGANIZATION INDEX;
Note ORGANIZATION INDEX: the whole table is just one big B-Tree, there is no table heap at all. Properties that belong to the same FOO_ID are stored physically close together, so retrieving all properties of the known FOO_ID will be cheap (but not as cheap as when all the properties were in the same row).
You might also want to consider whether it would be appropriate to:
Add more indexes in FOO_PROPERTY (e.g. for searching on property name or value). Just beware of the extra cost of secondary indexes in index-organized tables.
Switch the order of columns in the FOO_PROPERTY PK - if you predominantly search on property names and rarely retrieve all the properties of the given FOO_ID. This would also make the index compression feasible, since the leading edge of the index is now relatively wide string (as opposed to narrow integer).
Use a different type for VALUE (e.g. RAW, or even in-line BLOB/CLOB, which can have performance implications, but might also provide additional flexibility). Alternatively, you might even have a separate table for each possible value type, instead of stuffing everything in a string.
Separate property "declaration" to its own table. This table would have two keys: beside string NAME it would also have integer PROPERTY_ID which can then be used as a FK in FOO_PROPERTY instead of the NAME (saving some storage, at the price of more JOIN-ing).

Related

Adding a boolean coulmn into existing table of oracle database

I am using oracle database and I have a table named MyTitle and into this existing table I have to add a column of type boolean so the name of the column is IsChecked and the default value should be false of that column, I have tried the below way please advise is it correct or not
alter Table MyTitle add IsChecked Number(1) default 0 not null ;
It looks reasonable. Do you have a problem with it? Different people/ systems have different conventions for pseudo-boolean columns. Some use a number with 0 and 1. Some use a char(1) with a 'Y' and 'N'. Be consistent with whatever convention exists in your system.
I'd normally include a check constraint that limits the values in the column to the values you want, i.e.
check( isChecked in (0,1) )
If you're building a data warehouse, though, there are schools of thought that including check constraints like this is unnecessary overhead since there is (or should be) only a very small number of paths (ideally one) to load the data via the ETL process so you merely need to ensure that the ETL process isn't inserting invalid values.

Replace foreign key column with compressed index

I would like to spare some tables in my database.
One table for example has a simple Primary-Key-ID column and a VARCHAR2 column.
The VARCHAR2 column has NO duplicate values, yet different unique IDs.
The PK column of this table is just referenced once as a foreign key in another table.
My thoughts are now to insert the values from the VARCHAR2 column into the the table which has held the primary key.
I could now remove the foreign key reference, delete the table and gain a new column with all the (duplicate) VARCHAR2 values. These I would like to compress in a unique/distinct way.
I have heard about index in the Oracle Database to compress column(s) but I am not quite sure which index I need or how to use them...
The underlying feature (and storage savings) should be about as the same as it was with the previous table of unique values and the foreign key reference.
Thank you for your help in advance!
Oracle basic compression allows us to compress tables. It comes with several distinct limitations, not the least of which is that it isn't suitable for OLTP databases. Direct path inserts, updates and deletes don't benefit. So you can't do what you want that way. If your organisation has sprung for the Advanced Compression licence then you have more options, but the compression still works on the table not an individual column.
I think you've confused things with index compression, which does operate on columns, as it allows us to compress the leading column(s) of a compound index. But it's worth applying only when there's a lot of repetition in those columns. If your index has a unique ID for the leading column than compression will actually increase the total amount of space taken. (Just one reason why compound indexes should be built with the least selective column first and the most selective column last.)
Your table is a classic key-value lookup table. So you could consider converting it into an index-organized table. You would save yourself a bit of space by maintaining only a specialized index instead of a table and its primary key index. Find out more

Referential Integrity and Translations

Description
Hi, so I am looking at a legacy database that includes multiple translation tables for existing tables.
So there is a laws table, but then there is also a translation_laws table:
Laws (law_id, inForceDate, type, etc)
Translation_Laws (law_id, lang_code, translation)
There is also a law_type table:
Law_Type (law_type_id, description, isDecreed, etc.)
Translation_Law_Type(law_type_id, lang_code, translation)
So, with the following scheme referential integrity is maintained, but you end up with multiple translations tables.
I would prefer to make one table with the following format:
translations(table_name, id, lang_code, translation)`
This would basically be like bundle, key, lang_code, label. I could also combine bundle+key+lang_code into one varchar key: bundle.key.lang_code.
However, I don't see much of a way to define a relationship in Oracle SQL.
Questions:
Any Ideas how to define a relationship while using Integer IDs??
Would it be so bad to NOT to define a relationship in the database?
Only solution I can think of would be to try add a String foreign key to every table needing a translation (aaa.bbb.ccc.ddd) that is unique.
Update
Currently I have done away with the official relationships in the DB and made the following type of schema:
CREATE TABLE TRANSLATIONS(
DESCRIPTION_ENTITY VARCHAR(30) NOT NULL,
DESCRIPTION_COLUMN VARCHAR(30) NOT NULL,
KEY_OR_ID VARCHAR(30) NOT NULL,
LANG_CODE VARCHAR(2),
TEXT CLOB,
-- Legacy are To be able to cross check using columns - but not needed
LEGACY_TABLE VARCHAR(30) NOT NULL,
LEGACY_COLUMN VARCHAR(30) NOT NULL);
ALTER TABLE TRANSLATIONS
add CONSTRAINT UNIQUE_COMBINATION UNIQUE (DESCRIPTION_ENTITY, DESCRIPTION_COLUMN, KEY_OR_ID, LANG_CODE);
CREATE INDEX ind_description_entity ON TRANSLATIONS (DESCRIPTION_ENTITY);
CREATE INDEX ind_description_column ON TRANSLATIONS (DESCRIPTION_COLUMN);
CREATE INDEX ind_key_or_id ON TRANSLATIONS(KEY_OR_ID);
CREATE INDEX ind_lang_code ON TRANSLATIONS(LANG_CODE);
insert into TRANSLATIONS(DESCRIPTION_ENTITY, DESCRIPTION_COLUMN, KEY_OR_ID, LANG_CODE, TEXT, LEGACY_TABLE, LEGACY_COLUMN)
select 'LAW','TITLE', LAW_CODE, LANG_CODE, LAW_TITLE,
'LAW_TRANS','TITLE'
from LAW_TRANS where TITLE is not null;
Personally, I don't think there is anything wrong with not defining a relationship in a DB. At a massive investment bank where I was working before our Oracle specialists NEVER defined the relationships for performance reasons.
The basic question for your setup is, do you need a defined amount of languages or do you have to be flexible with adding languages later? If not, your approach is almost too flexible. Just adding different rows with the translation into the Laws table would be much more performant if you know you only every need 4 different languages.
Alternatively, you could just build a lock-up table:
original-string -> translated-string
And you can ignore the table name completely.

oracle- index organized table

what is use-case of IOT (Index Organized Table) ?
Let say I have table like
id
Name
surname
i know the IOT but bit confuse about the use case of IOT
Your three columns don't make a good use case.
IOT are most useful when you often access many consecutive rows from a table. Then you define a primary key such that the required order is represented.
A good example could be time series data such as historical stock prices. In order to draw a chart of the stock price of a share, many rows are read with consecutive dates.
So the primary key would be stock ticker (or security ID) and the date. The additional columns could be the last price and the volume.
A regular table - even with an index on ticker and date - would be much slower because the actual rows would be distributed over the whole disk. This is because you cannot influence the order of the rows and because data is inserted day by day (and not ticker by ticker).
In an index-organized table, the data for the same ticker ends up on a few disk pages, and the required disk pages can be easily found.
Setup of the table:
CREATE TABLE MARKET_DATA
(
TICKER VARCHAR2(20 BYTE) NOT NULL ENABLE,
P_DATE DATE NOT NULL ENABLE,
LAST_PRICE NUMBER,
VOLUME NUMBER,
CONSTRAINT MARKET_DATA_PK PRIMARY KEY (TICKER, P_DATE) ENABLE
)
ORGANIZATION INDEX;
Typical query:
SELECT TICKER, P_DATE, LAST_PRICE, VOLUME
FROM MARKET_DATA
WHERE TICKER = 'MSFT'
AND P_DATE BETWEEN SYSDATE - 1825 AND SYSDATE
ORDER BY P_DATE;
Think of index organized tables as indexes. We all know the point of an index: to improve access speeds to particular rows of data. This is a performance optimisation of trick of building compound indexes on sub-sets of columns which can be used to satisfy commonly-run queries. If an index can completely satisy the columns in a query's projection the optimizer knows it doesn't have to read from the table at all.
IOTs are just this approach taken to its logical confusion: buidl the index and throw away the underlying table.
There are two criteria for deciding whether to implement a table as an IOT:
It should consists of a primary key (one or more columns) and at most one other column. (okay, perhaps two other columns at a stretch, but it's an warning flag).
The only access route for the table is the primary key (or its leading columns).
That second point is the one which catches most people out, and is the main reason why the use cases for IOT are pretty rare. Oracle don't recommend building other indexes on an IOT, so that means any access which doesn't drive from the primary key will be a Full Table Scan. That might not matter if the table is small and we don't need to access it through some other path very often, but it's a killer for most application tables.
It is also likely that a candidate table will have a relatively small number of rows, and is likely to be fairly static. But this is not a hard'n'fast rule; certainly a huge, volatile table which matched the two criteria listed above could still be considered for implementations as an IOT.
So what makes a good candidate dor index organization? Reference data. Most code lookup tables are like something this:
code number not null primary key
description not null varchar2(30)
Almost always we're only interested in getting the description for a given code. So building it as an IOT will save space and reduce the access time to get the description.

SQL Timeout and indices

Changing and finding stuff in a database containing a few dozen tables with around half a million rows in the big ones I'm running into timeouts quite often.
Some of these timeouts I don't understand. For example I got this table:
CREATE TABLE dbo.[VPI_APO]
(
[Key] bigint IDENTITY(1,1) NOT NULL CONSTRAINT [PK_VPI_APO] PRIMARY KEY,
[PZN] nvarchar(7) NOT NULL,
[Key_INB] nvarchar(5) NOT NULL,
) ON [PRIMARY]
GO
ALTER TABLE dbo.[VPI_APO] ADD CONSTRAINT [IX_VPI_APOKey_INB] UNIQUE NONCLUSTERED
(
[PZN],
[Key_INB]
) ON [PRIMARY]
GO
I often get timeouts when I search an item in this table like this (during inserting high volumes of items):
SELECT [Key] FROM dbo.[VPI_APO] WHERE ([PZN] = #Search1) AND ([Key_INB] = #Search2)
These timeouts when searching on the unique constraints happen quite often. I expected unique constraints to have the same benefits as indices, was I mistaken? Do I need an index on these fields, too?
Or will I have to search differently to benefit of the constraint?
I'm using SQL Server 2008 R2.
A unique constraint creates an index. Based on the query and the constraint defined you should be in a covering situation, meaning the index provides everything the query needs without a need to back to the cluster or the heap to retrieve data. I suspect that your index is not sufficiently selective or that your statistics are out of date. First try updating the statistics with sp_updatestats. If that doesn't change the behavior, try using UPDATE STATISTICS VPI_APO WITH FULL SCAN. If neither of those work, you need to examine the selectivity of the index using DBCC SHOW_STATISTICS.
My first thought is parameter sniffing.
If you're on SQL Server 2008, try "OPTIMIZE FOR UNKNOWN" rather than parameter masking
2nd thought is change the unique constrant to an index and INCLUDE the Key column explicitly. Internally they are the same, but as an index you have some more flexibility (eg filter, include etc)

Resources