Thanks for your patience. Even without a primary key there must be *some* indicator of what you have extracted, otherwise there no way to compare what you have already got with what is new. Worst case is that you need to examine every column to make that decision.
In any event, 85 million rows is large but not huge.
For not null columns you can do a direct comparison. For nullable columns, you can use map them a special value just for matching purposes. So you can do something like this:
SQL> create table t1 as
2 select d.owner, d.object_name, d.object_type, d.created
3 from dba_objects d,
4 ( select 1 from dual connect by level <= 1000 );
Table created.
SQL> desc t1
Name Null? Type
----------------------------------------------------------------- -------- -------------
OWNER NOT NULL VARCHAR2(128)
OBJECT_NAME NOT NULL VARCHAR2(128)
OBJECT_TYPE NOT NULL VARCHAR2(23)
CREATED DATE
SQL> select count(*) from t1;
COUNT(*)
----------
72952002
--
-- our initial copy
--
SQL> create table t2 as
2 select * from t1;
Table created.
--
-- some new rows
--
SQL> insert into t1
2 values ('NEW','CONNOR','INDEX',sysdate);
1 row created.
SQL>
SQL> insert into t1
2 values ('NEW','CONNOR','TABLE',sysdate);
1 row created.
SQL>
SQL> commit;
Commit complete.
SQL> set timing on
SQL> with
2 t1x as ( select rowid rid,owner,object_name,object_type,nvl(created,date '2000-01-01') created from t1),
3 t2x as ( select rowid rid,owner,object_name,object_type,nvl(created,date '2000-01-01') created from t2)
4 select t1x.rid
5 from t1x
6 where owner is not null
7 and object_name is not null
8 and object_type is not null
9 and created is not null
10 and (owner,object_name,object_type,created) not in
11 ( select owner,object_name,object_type,created
12 from t2x
13 where owner is not null
14 and object_name is not null
15 and object_type is not null
16 and created is not null
17 );
RID
------------------
AAASN7AANAACZzZAAB
AAASN7AANAACZzZAAA
2 rows selected.
Elapsed: 00:02:53.81
So 3mins isn't too bad (on my home machine). Obviously this will not scale over time as the volumes get larger, but it should get you by ?
And if needs be, you could smash it with parallel ?
SQL> set timing on
SQL> with
2 t1x as ( select rowid rid,owner,object_name,object_type,nvl(created,date '2000-01-01') created from t1),
3 t2x as ( select rowid rid,owner,object_name,object_type,nvl(created,date '2000-01-01') created from t2)
4 select /*+ parallel */ t1x.rid
5 from t1x
6 where owner is not null
7 and object_name is not null
8 and object_type is not null
9 and created is not null
10 and (owner,object_name,object_type,created) not in
11 ( select owner,object_name,object_type,created
12 from t2x
13 where owner is not null
14 and object_name is not null
15 and object_type is not null
16 and created is not null
17 );
RID
------------------
AAASN7AANAACZzZAAA
AAASN7AANAACZzZAAB
Elapsed: 00:01:11.71