19

An old system have arrived on our office for some changes and fix, but it is also suffering from performance issues. We don't know exactly what is the source of this slowness.

While we were refactoring the old code we found several sql queries with the follow pattern (the queries are simplified for example purpose):

SELECT
   (
    SELECT X
    FROM A
    WHERE A.id = TABLE.id
   ) AS COLUMN1,
    (
    SELECT Y
    FROM B
    WHERE B.id = TABLE.id
   ) AS COLUMN1,
   (
    SELECT Z
    FROM C
    WHERE C.id = TABLE.id
   ) AS COLUMN1,
   ...
FROM
    TABLE
WHERE
    TABLE.id = @param;

These queries do several internal sub queries from every column they return.

We are planning to rewrite these queries on the follow pattern:

SELECT
    A.X, B.Y, C.Z
FROM
    TABLE
    INNER JOIN A on A.ID = TABLE.ID
    INNER JOIN B on B.ID = TABLE.ID
    INNER JOIN C on C.ID = TABLE.ID
WHERE
    TABLE.id = @param;

With inner joins they are easier to read and understand, but is it really any faster? Is it the better way to write them? Unfortunately the first one we rewrote didn't improve the query time, it made the query a bit slower.

Here is my question: should we rewriting all these queries? Are these sub-queries a good way to do this job? Are they faster the the inner-join way?

Gustavo Cardoso
  • 747
  • 2
  • 7
  • 20
  • Tom (Kyte, of Oracle fame) gave a nice (and short) answer to a very similar question here: ["joins vs subquery , Exists clause "](https://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:66812779016023) – David Balažic Jul 24 '14 at 13:49

5 Answers5

16

If I understand your question correctly, you are starting an operation to rewrite some of your SQL statements because you THINK there might be an issue with them.

My advice is to stop and first start to determine where your time is currently being spent. Only after you have found that it's in the queries with those scalar subselects AND it's because of those scalar subselects, you should be rewriting them. Until then: start tracing and examining.

Here are two threads from OTN that are used to guide people with performance problems:

http://forums.oracle.com/forums/thread.jspa?messageID=1812597 http://forums.oracle.com/forums/thread.jspa?threadID=863295

Regards,
Rob.

And: because of scalar subquery caching, your original query might be a lot faster than a rewritten query using joins.

Rob van Wijk
  • 17,555
  • 5
  • 39
  • 55
  • 2
    Your answer told me exactly something that I didn't kwon about: "scalar subquery caching". Perhaps the sub queries can be good sometimes.However, we rewrote another query and got a really better result, from 0.5s to 0.04s. I'm signing your post as teh correct one because for some people the sub queries maybe be a good solution indeed. Thank you. – Gustavo Cardoso Feb 07 '11 at 13:46
10

subquery actually runs once for every row whereas the join happens on indexes.

Use joins for better readability and maintainability as you have already mentioned in your questions.

Sachin Shanbhag
  • 54,530
  • 11
  • 89
  • 103
  • Why? if there is an index, it should apply for a simple id search. – Adam Matan Feb 07 '11 at 12:32
  • Sometimes the table are not joined by their indexed columns. Do it affect the preference for inner join? – Gustavo Cardoso Feb 07 '11 at 12:40
  • 3
    @Adam,@Gustavo - The performance depends on the database engine you are running the queries. You have to check the performance using the execution plan(not sure what exactly it is called in oracle). Sometimes subqueries are better, sometimes joins, but finally for better readability and maintaining queries, joins have a slight advantage. – Sachin Shanbhag Feb 07 '11 at 12:47
  • 1
    Because of scalar subquery caching, this answer is not always true. – Rob van Wijk Feb 07 '11 at 13:22
4

Joins will give you better performance, but I recommend taking a look at the execution plan whenever "optimising" queries.

dogbane
  • 266,786
  • 75
  • 396
  • 414
2

As this answer argues, it should not affect the performance. However, some query optimizers might perform better on JOINs, so you should make some experiments on your system.

And now for something completely different: JOINing each table to the next one might be more aesthetic than JOINing all with TABLE, and prevents errors whenever the id appears more than once in one of the tables:

SELECT
    A.X, B.Y, C.Z
FROM
    TABLE
    INNER JOIN A on A.ID = TABLE.ID
    INNER JOIN B on A.ID = B.ID
    INNER JOIN C on B.ID = C.ID
WHERE
    TABLE.id = @param;
Community
  • 1
  • 1
Adam Matan
  • 128,757
  • 147
  • 397
  • 562
  • Thank you for the example. For sure it is better to read. On my example there are only 3 joins, but every query here do it 10 or more times per query... – Gustavo Cardoso Feb 07 '11 at 12:42
0

Here inner joining is better. Below are the reasons:

1- In your main query, you are referring/using the values from the table used in sub query. Join is meant for this. Your ask is - "Get me some values by joining different tables as these can not be obtained from one table".

Sub query should be used when columns from sub query is not referred in the main query. Like:

select * from emp where deptno in ( select deptno from dept ); 

Here you are asking- "Get me all employees who works in department number deptno". You are not much concerned about this deptno in dept.

2- Another reason is readability, that you already mentioned.

3- Performance-wise you need not worry as optimizer knows what to do.

For more details, please check here.

Dexter
  • 4,036
  • 3
  • 47
  • 55
  • for oracle all of the above statements are certainly not true in all cases. there are cases where subqueries can improve preformance significantly. https://www.oratechinfo.co.uk/scalar_subqueries.html also I think you are talking about something else than scalar subqueries. – Epicycle Feb 24 '22 at 18:36