I am in Oracle SQL developer and trying to create a table from two existing tables.
The existing tables contain the records of 1 million from where we are creating this new table temporary and
T1.id and T2.id columns are having indexes.
The Create table query mentioned below is the one which I am using and it is taking around 2 hours to create the table for 1 million records.
I need to optimize this query to reduce the time for table creation.
CREATE TABLE temporary
AS
( SELECT /*+ parallel (T1,8)(T2,8)*/
T1.id,
T2.name,
T2.code
FROM
TABLE1 T1,
TABLE2 T2
WHERE
T2.id = T1.id
AND T2.code IN ( 'TYPE', 'SYS' )
);
I need to optimize this query to reduce the time for table creation.
Related
There is table with 412499154 records, I have to recreate based on where condition. The table has 6 columns and all of varchar2() datatype.
when I recreate with the entire content, it takes roughly around 10 minutes.
CREATE TABLE TEMP_NEW_01 NOLOGGING
AS
SELECT COL1,COL2,COL3,COL4,COL5,COL6
FROM TEMP_DATA ;
When a where clause is included, its running indefinitely,
CREATE TABLE TEMP_NEW_01 NOLOGGING
AS
select COL1,COL2,COL3,COL4,COL5,COL6
FROM TEMP_DATA
WHERE COL1 IN
(SELECT COL1 FROM temp_m2
where SHORT_CAPTION in ( select SHORT_CAPTION from t_category
where scat_caption in ('P','V'))
);
Any suggestions for improving? Thanks!
Instead of using (nested) subqueries, join tables.
Make sure columns you use in joins are indexed; if not, then:
CREATE INDEX i1_dat_col1 ON temp_data (col1);
CREATE INDEX i1_m2_col1 ON temp_m2 (col1);
CREATE INDEX i2_m2_capt ON temp_m2 (short_caption);
CREATE INDEX i1_cat_capt ON t_category (short_caption);
Gather statistics on all tables and indexes before running the CREATE TABLE statement!
Finally:
CREATE TABLE temp_new_01
AS
SELECT d.col1,
d.col2,
d.col3,
d.col4,
d.col5,
d.col6
FROM temp_data d
JOIN temp_m2 m ON m.col1 = d.col1
JOIN t_category c ON c.short_caption = m.short_caption
WHERE c.scat_caption IN ('P', 'V');
In SQLite I have two tables, T1 and T2. They have exactly the same number of records.
I can run the following command to create a new column in T1
alter table T1 add column t2_col;
Suppose T2 only has one column. How do I replace the t2_col's content with T2's row by row (by rowid essentially).
Use a subquery to read the value from the corresponding T2 record:
UPDATE T1
SET t2_col = (SELECT t2_col
FROM T2
WHERE T2.rowid = T1.rowid)
NOTE: I'm currently running my queries in question on a sqlite3 DB, though answers from expertise in any other DBMS will be welcome insight...
I was wondering if the query optimizer makes any attempt to identify repeated queries/subqueries and run them only once if so.
Here is my example query:
SELECT *
FROM table1 AS t1
WHERE t1.fk_id =
(
SELECT t2.fk_id
FROM table2 AS t2
WHERE t2.id = 1111
)
OR t1.fk_id =
(
SELECT local_id
FROM ID_MAP
WHERE remote_id =
(
SELECT t2.fk_id
FROM table2 AS t2
WHERE t2.id = 1111
)
);
Will the nested query
SELECT t2.fk_id
FROM table2 AS t2
WHERE t2.id = 1111
be run only once (and its results cached for further access) ?
Its not a big deal in this example, since its a simple query that executes only twice, however I need it to run
about 4-5 more times (x2, twice for each child record, so 8-10 really) in my actual program (its grabbing all child records (table1)
associated to a parent record (table2), bound by a foreign key. Its also checking an id mapping table to make sure it queries
for both a locally generated id, as well as the real/updated/new key).
I really appreciate any help with this, thank you.
SQLite has a very simple query optimizer, and does not even try to detect identical subqueries:
> create table t(x);
> explain query plan
select * from t
where x in (select x from t) or
x in (select x from t);
0|0|0|SCAN TABLE t (~500000 rows)
0|0|0|EXECUTE LIST SUBQUERY 1
1|0|0|SCAN TABLE t (~1000000 rows)
0|0|0|EXECUTE LIST SUBQUERY 2
2|0|0|SCAN TABLE t (~1000000 rows)
The same applies to CTEs and views; if the performance actually matters, your best bet is to create a temporary table for the result of the subquery.
As you asked for insight from other DBs....
In Oracle DBMS, any independent subquery will be executed only once.
SELECT t2.fk_id
FROM table2 AS t2
WHERE t2.id = 1111 -- The result will be the same for any row in t1.
Dependant subqueries will need to executed repeatedly, of course.
Example of dependent subquery:
SELECT t2.fk_id
FROM table2 AS t2
WHERE t2.id = t1.t2_id -- t1.t2_id will have different values for different rows in t1.
I have this statement:
update new_table t2
set t2.creation_date_utc =
(select creation_date from old_table t1 where t2.id = t1.id)
where exists
(select 1 from old_table t1 where t2.id = t1.id);
The cost according to the explain plan is 150959919. The explain plan shows some full table access for a total cost of like 3000, and then the update has that basically infinite cost. It indeed seems to go on forever if run.
FYI, these tables have no more than 300k rows each.
In addition, this query.
select
(select creation_date from old_table t1 where t2.id = t1.id)
from new_table t2;
finishes basically instantly.
What could be the cause of this?
if you have an update statement in the format that you mentioned, then it implies that the id field is unique across the old_table (otherwise the first inner query would have raised error returning multiple values for update when in fact, only one value can be processed). So, you can modify your first query to be(removing the where clause since it is redundant) :-
update new_table t2
set t2.creation_date_utc =
(select creation_date from old_table t1 where t2.id = t1.id);
it might be possible that the above query will still take a long time owing to full table scans. So, you have two options :-
apply an index to the old_table table on the id field using the following command.
Create index index_name on old_table(id);
modify your update query to the following (untested) :-
update new_table t2
set t2.creation_date_utc=
(select creation_date from old_table t1 where t2.id=t1.id and rownum=1);
The rownum=1 should instruct oracle not to do any more searching as soon as the first match is found in old_table.
I would recommend the first approach though.
You don't have an index on old_table.id and nested loop joins are very expensive. An index on old_table(id, creation_date) would be best.
Why not use merge statement? I've found it to be more efficient in similar cases.
merge into new_table t2
using old_table t1
on (t2.id = t1.id)
when matched then
update set t2.creation_date_utc = t1.creation_date;
This may be faster and equivalent:
update new_table t2
set t2.creation_date_utc =
(select creation_date from old_table t1 where t2.id = t1.id)
where t2.id in
(select id from old_table t1);
How to create a table by copying only the columns from multiple tables??
eg. t1 with fields (A1,A2,A3)
t2 with fiedls (D1,D2,D3)
t3 with fields (Z1,Z2,Z3)
Now I've to create a new table using only the fields not the values from the above three tables i.e.
new_tbl (A1,A2,A3,D1,D2,D3,Z1,Z2,Z3)
How can I do it??
try this:
create table new_tbl as
select *
from t1
join t1 on 1=2
join t3 on 1=2
the condition 1=2 is always false.. so it will not return any data but the column header..