Assuming that b.column3 has a primary/unique key constraint on it, left joining B makes no difference to the result.
This is because for each row in A, you have
at most one row in B. Unlike an inner join, an outer join preserves all the rows from the driving table (A). So there's no need to read B.
But to do this optimization, you must have a constraint enforcing uniqueness:
set serveroutput off
create table t1 (
c1 int
);
create table t2 (
c1 int
);
insert into t1 values ( 1 );
insert into t1 values ( 2 );
insert into t2 values ( 1 );
commit;
select count (*) from t1
left join t2
on t1.c1 = t2.c1;
select *
from table(dbms_xplan.display_cursor(null, null, 'BASIC LAST'));
EXPLAINED SQL STATEMENT:
------------------------
select count (*) from t1 left join t2 on t1.c1 = t2.c1
Plan hash value: 4045007133
------------------------------------
| Id | Operation | Name |
------------------------------------
| 0 | SELECT STATEMENT | |
| 1 | SORT AGGREGATE | |
| 2 | HASH JOIN OUTER | |
| 3 | TABLE ACCESS FULL| T1 |
| 4 | TABLE ACCESS FULL| T2 |
------------------------------------
alter table t2 add primary key ( c1 );
select count (*) from t1
left join t2
on t1.c1 = t2.c1;
select *
from table(dbms_xplan.display_cursor(null, null, 'BASIC LAST'));
EXPLAINED SQL STATEMENT:
------------------------
select count (*) from t1 left join t2 on t1.c1 = t2.c1
Plan hash value: 1634389831
-----------------------------------
| Id | Operation | Name |
-----------------------------------
| 0 | SELECT STATEMENT | |
| 1 | SORT AGGREGATE | |
| 2 | TABLE ACCESS FULL| T1 |
-----------------------------------