I understand that a view is a window to an underlying table or set of tables in Oracle. For instance if I have a view that is created by joining multiple tables , will the view perform the actual join operations when I select data from the view? Does a view perform better than joining multiple tables to fetch data or is it the same with respect to performance?
There is usually no performance difference between a single query and a logically equivalent query that uses views.
Oracle has optimizer transformations that can combine views with the outer query; predicate pushing, simple and complex view merging, etc. Think of views more like a text macro that builds a large query, instead of a function that returns rows.
For example, in the below query Oracle would probably be smart enough to push the predicate on the primary key column into the view. Although the view by itself might return millions of rows, when the entire query is run Oracle will apply the predicate on the primary key column first.
select *
from view_returns_millions_of_rows
where primary_key_value = 1;
Related
When materialized views are created in Oracle, do they store indices or do they store actual table values?
I am asking this as creating index on table and using views on that table and using materialized views (created with refresh complete start with (sysdate) next (sysdate+1) with rowid as) on unindexed table gives similar performance.
Where as I would expect materialized views to be far more faster.
Update
I slightly modified the content/title. My current concern after discussion is if materialized views are actual real tables or virtual tables with some optimization.
Materialized views create a copy of the data. To all intents and purposes they are actual tables. In fact we can create a materialized view from an existing table using the PREBUILT clause. The only difference is how the data is mastered - a materialized view doesn't own its data, a table does.
As to your performance conundrum:
When you say "on unindexed table" do you literally mean one table? If so, we wouldn't expect any difference in the time to query a view, a materialized view or the actual data: they all execute a full table scan on the same volume of data.
Consider the case where views have expecting select * from <table> where <condition>.
We would a SELECT against a materialised view built on that query to execute quicker than the same SELECT against the actual table, provided the WHERE clause restricts the data to a significantly smaller subset of the original data. Simply because a full table scan over a small table (materialised view) takes less time than a full table scan over a big table. Same applies if the materialised view's projection has fewer columns than the base table.
Indexing is a different matter. Unless the query selects a very small subset of the data it's not going to be more efficient than a full table scan and a filter.
To sum up: the only universal tuning heuristic is: it takes less time to do less work. Beyond that it is impossible to generalise. We can't discuss some vague "consider the case where views have select * from <table> where <condition>." It's all about the specifics.
Fundamentally, a materialized view is just a table with an associated query to populate it.
Given static data, one would generally expect the performance of a SELECT * from the materialized view (with no WHERE clause) to be at least as fast as running the query that underlies the materialized view, regardless of indexing.
If we add a WHERE clause to a SELECT * against the mview, however, that query could perform significantly slower than running the query that underlies the mview with the same WHERE clause. That's because the tables referenced in the query underlying the mview could have indexes to support the conditions in the WHERE clause, where as the mview might not have such indexes.
As per title, is it possible to write my own query in OracleSQL Developer and then plug it into Oracle Peoplesoft? Or is it possible to have a pivot query in Peoplesoft?
Yes, you can do that using a view.
After that you will create a new Query using your view, and if you want to, use the query as datasource for your pivot grid
Oracle PIVOT clauses are not supported, nor are any other database pivot-like clauses. And as suggested by Walucas, you can use a view with the PIVOT clause already written and then query the view. An alternate approach would be to use a series of left outer joins where each join is to the same table, each with a mutually exclusive set of rows. This is a hammer-like approach and very inelegant, but you can do this without having to create a view.
I have created a materialized view with Refresh complete like that and it works well:
CREATE MATERIALIZED VIEW VM4
Build immediate
refresh complete on commit
AS
select C.codecomp,
count(c.numpolice) as NbContrat,
SUM(c.montant) as MontantGlobal
from contrat C
group by c.codecomp;
Now I would like to create a similar view but with Refresh Fast but it dosn't work and it shows me this error:
error
Knowing that I have already created the LOG of the Contrat table ilke that:
CREATE MATERIALIZED VIEW LOG ON contrat with rowid ;
Check documentation:
General Restrictions on Fast Refresh
The defining query of the materialized view is restricted as follows:
The materialized view must not contain references to non-repeating expressions like SYSDATE and ROWNUM.
The materialized view must not contain references to RAW or LONG RAW data types.
It cannot contain a SELECT list subquery.
It cannot contain analytic functions (for example, RANK) in the SELECT clause.
It cannot reference a table on which an XMLIndex index is defined.
It cannot contain a MODEL clause.
It cannot contain a HAVING clause with a subquery.
It cannot contain nested queries that have ANY, ALL, or NOT EXISTS.
It cannot contain a [START WITH …] CONNECT BY clause.
It cannot contain multiple detail tables at different sites.
ON COMMIT materialized views cannot have remote detail tables.
Nested materialized views must have a join or aggregate.
Materialized join views and materialized aggregate views with a GROUP BY clause cannot select from an index-organized table.
Restrictions on Fast Refresh on Materialized Views with Aggregates
Defining queries for materialized views with aggregates or joins have
the following restrictions on fast refresh:
All restrictions from "General Restrictions on Fast Refresh".
Fast refresh is supported for both ON COMMIT and ON DEMAND
materialized views, however the following restrictions apply:
All tables in the materialized view must have materialized view logs, and the materialized view logs must:
Contain all columns from the table referenced in the materialized view.
Specify with ROWID and INCLUDING NEW VALUES.
Specify the SEQUENCE clause if the table is expected to have a mix of inserts/direct-loads, deletes, and updates.
Only SUM, COUNT, AVG, STDDEV, VARIANCE, MIN and MAX are supported for fast refresh.
COUNT(*) must be specified.
Aggregate functions must occur only as the outermost part of the expression. That is, aggregates such as AVG(AVG(x)) or AVG(x)+ AVG(x)
are not allowed.
For each aggregate such as AVG(expr), the corresponding COUNT(expr) must be present. Oracle recommends that SUM(expr) be
specified. See Requirements for Using Materialized Views with
Aggregates for further details.
If VARIANCE(expr) or STDDEV(expr) is specified, COUNT(expr) and SUM(expr) must be specified. Oracle recommends that SUM(expr *expr) be
specified. See Requirements for Using Materialized Views with
Aggregates for further details.
The SELECT column in the defining query cannot be a complex expression with columns from multiple base tables. A possible
workaround to this is to use a nested materialized view.
The SELECT list must contain all GROUP BY columns.
The materialized view is not based on one or more remote tables.
If you use a CHAR data type in the filter columns of a materialized view log, the character sets of the master site and the
materialized view must be the same.
If the materialized view has one of the following, then fast refresh is supported only on conventional DML inserts and direct
loads.
Materialized views with MIN or MAX aggregates
Materialized views which have SUM(expr) but no COUNT(expr)
Materialized views without COUNT(*)
Such a materialized view is called an insert-only materialized view.
A materialized view with MAX or MIN is fast refreshable after delete or mixed DML statements if it does not have a WHERE clause.
The max/min fast refresh after delete or mixed DML does not have the same behavior as the insert-only case. It deletes and recomputes
the max/min values for the affected groups. You need to be aware of
its performance impact.
Materialized views with named views or subqueries in the FROM clause can be fast refreshed provided the views can be completely
merged. For information on which views will merge, see Oracle Database
SQL Tuning Guide.
If there are no outer joins, you may have arbitrary selections and joins in the WHERE clause.
Materialized aggregate views with outer joins are fast refreshable after conventional DML and direct loads, provided only the
outer table has been modified. Also, unique constraints must exist on
the join columns of the inner join table. If there are outer joins,
all the joins must be connected by ANDs and must use the equality (=)
operator.
For materialized views with CUBE, ROLLUP, grouping sets, or concatenation of them, the following restrictions apply:
The SELECT list should contain grouping distinguisher that can either be a GROUPING_ID function on all GROUP BY expressions or
GROUPING functions one for each GROUP BY expression. For example, if
the GROUP BY clause of the materialized view is "GROUP BY CUBE(a, b)",
then the SELECT list should contain either "GROUPING_ID(a, b)" or
"GROUPING(a) AND GROUPING(b)" for the materialized view to be fast
refreshable.
GROUP BY should not result in any duplicate groupings. For example, "GROUP BY a, ROLLUP(a, b)" is not fast refreshable because it
results in duplicate groupings "(a), (a, b), AND (a)".
I think you missed
COUNT(*) must be specified.
For each aggregate such as AVG(expr), the corresponding COUNT(expr) must be present.
Specify with ROWID and INCLUDING NEW VALUES.
Specify the SEQUENCE clause if the table is expected to have a mix of inserts/direct-loads, deletes, and updates.
Is it possible to do updates via Resultset to an Oracle view? Asking as my code is giving me insufficient priviledge error when it does the rs.updateRow() call. I have checked and I definitely have access to the table/view.
The code looks like:
white (rs.next()) {
int updateStatus = getPSCforAction(status);
rs.updateInt("SPSC", updateStatus);
rs.updateRow;
}
The SELECT statement changes depends on operation but it will always be querying an Oracle view (and in some cases multiple views). My main question is whether updating via resultSet can be done to an Oracle view (or views)?
To answer your question one must see a definition of you view and a SELECT statament that is used to produce the resulset in your Java code. Without looking at this it is hard to give the answer
Anyway, generar rules and limitations are described in the Oracle Database JDBC Developer's guide:
Result Set Limitations
The following limitations are placed on queries for enhanced result
sets. Failure to follow these guidelines results in the JDBC driver
choosing an alternative result set type or concurrency type.
To produce an updatable result set:
A query can select from only a single table and cannot contain any
join operations.
In addition, for inserts to be feasible, the query must select all
non-nullable columns and all columns that do not have a default value.
A query cannot use SELECT * . However, there is a workaround for this.
A query must select table columns only.
It cannot select derived columns or aggregates, such as the SUM or MAX
of a set of columns.
To produce a scroll-sensitive result set:
A query cannot use SELECT *. However, there is a workaround for this.
A query can select from only a single table.
Scrollable and updatable result sets cannot have any column as Stream.
When the server has to fetch a Stream column, it reduces the fetch
size to one and blocks all columns following the Stream column until
the Stream column is read. As a result, columns cannot be fetched in
bulk and scrolled through.
They vaguely write that:
A query can select from only a single table and cannot contain any
join operations.
Could be that they mean "exlusively from tables, but not views", but also they could mean: "from tables and views", nobody knows, one must test this.
Another possible problem - your view may not be updatable, that is it doesn't conform to the following rules:
Notes on Updatable Views The following notes apply to updatable views:
An updatable view is one you can use to insert, update, or delete base
table rows. You can create a view to be inherently updatable, or you
can create an INSTEAD OF trigger on any view to make it updatable.
To learn whether and in what ways the columns of an inherently
updatable view can be modified, query the USER_UPDATABLE_COLUMNS data
dictionary view. The information displayed by this view is meaningful
only for inherently updatable views. For a view to be inherently
updatable, the following conditions must be met:
Each column in the view must map to a column of a single table. For
example, if a view column maps to the output of a TABLE clause (an
unnested collection), then the view is not inherently updatable.
The view must not contain any of the following constructs:
A set operator
A DISTINCT operator
An aggregate or analytic function
A GROUP BY, ORDER BY, MODEL, CONNECT BY, or START WITH clause
A collection expression in a SELECT list
A subquery in a SELECT list
A subquery designated WITH READ ONLY Joins, with some exceptions, as
documented in Oracle Database Administrator's Guide
In addition, if an
inherently updatable view contains pseudocolumns or expressions, then
you cannot update base table rows with an UPDATE statement that refers
to any of these pseudocolumns or expressions.
If you want a join view to be updatable, then all of the following
conditions must be true:
The DML statement must affect only one table underlying the join.
For an INSERT statement, the view must not be created WITH CHECK
OPTION, and all columns into which values are inserted must come from
a key-preserved table. A key-preserved table is one for which every
primary key or unique key value in the base table is also unique in
the join view.
For an UPDATE statement, the view must not be created WITH CHECK
OPTION, and all columns updated must be extracted from a key-preserved
table.
For a DELETE statement, if the join results in more than one
key-preserved table, then Oracle Database deletes from the first table
named in the FROM clause, whether or not the view was created WITH
CHECK OPTION.
Let's assume I have two tables of the same row count. Both tables contain a column that allows for 1-1 join between them.
If those tables were turned into one table instead and thus JOIN statement eliminated from the query, would there be any performance benefit of that?
Another example... Let's assume I have table with 10 columns. From that table I created new table but only taking one column. If I issue statement selecting that one column with WHERE predicate on the same column would there be any performance difference in executing this query on both tables?
What I'm trying to get to is if performance is the same in above cases is it safe to say tables are only containers wrapping number of columns together?
I did run couple tests but with non conclusive results.
Let's assume I have two tables of the same row count. Both tables
contain a column that allows for 1-1 join between them. If those
tables were turned into one table instead and thus JOIN statement
eliminated from the query, would there be any performance benefit of
that?
Performing that join for every query is of course more expensive than materializing the table once and then reading it. So yes, there would be a performance benefit.
Another example... Let's assume I have table with 10 columns. From
that table I created new table but only taking one column. If I issue
statement selecting that one column with WHERE predicate on the same
column would there be any performance difference in executing this
query on both tables?
No, there would be no difference, since tables are represented as collections of columns, which are each stored in their own file.
What I'm trying to get to is if performance is the same in above cases
is it safe to say tables are only containers wrapping number of
columns together?
That is indeed safe to say.