retagged
21,996 views
88 88 votes

Consider the following relation schemas :

  • b-Schema = (b-name, b-city, assets)
  • a-Schema = (a-num, b-name, bal)
  • d-Schema = (c-name, a-number)

Let branch, account and depositor be respectively instances of the above schemas. Assume that account and depositor relations are much bigger than the branch relation.

Consider the following query:

Пc-nameb-city = "Agra" ⋀ bal < 0 (branch ⋈ (account ⋈ depositor)

Which one of the following queries is the most efficient version of the above query ?

  1. Пc-namebal < 0 b-city = "Agra" branch ⋈ account) ⋈ depositor)
  2. Пc-nameb-city = "Agra" branch ⋈ (σbal < 0 account ⋈ depositor))
  3. Пc-name ((σb-city = "Agra" branch ⋈ σb-city = "Agra" ⋀  bal < 0 account) ⋈ depositor)
  4. Пc-nameb-city = "Agra" branch ⋈ (σb-city = "Agra" ⋀  bal < 0 account ⋈ depositor))

5 Answers

Best answer
87 87 votes

It should be A. As in B we are doing a join between two massive table whereas in A we are doing join between relatively smaller table and larger one and the output that this inner table gives (which is smaller in comparison to joins that we are doing in B) is used for join with depositer table with the selection condition.

Options C and D are invalid as there is no b-city column in a-Schema.


Lets see in detail. Let there be 100 different branches. Say about $10$% of accounts are below $0$. Also, let there be $10,000$ accounts in a branch amounting to $1,000,000$ total accounts. A customer can have multiple accounts, so let there be on average $2$ accounts per customer. So, this amounts to $2,000,000$ total entries in depositor table. Lets assume these assumptions are true for all the branches. So, now lets evaluate options A and B.

1. All the accounts in Agra branch, filter by positive balance, and then depositor details of them. So, 

  • Get branch name from branch table after processing $100$ records
  • Filter $10,000$ accounts after processing $1,000,000$ accounts belonging to Agra
  • Filter 1000 accounts after processing 10,000 accounts for positive balance
  • Get $500$ depositor details after processing $2,000,000$ entries for the given $1000$ accounts (assuming $1$ customer having $2$ accounts). So, totally this amounts to $2,000,000,000$ record processing.
  • So totally $\approx$ 2 billion records needs processing.

2. All the positive balance accounts are found first, and then those in Agra are found.

  • Filter $100,000$ accounts after processing $1,000,000$ accounts having positive balance
  • Find the deposito details of these accounts. So, $100,000 $*$ 2,000,000$ records need processing and this is a much larger value than for query A. Even if we reduce the percentage of positive balance ($10$ we assumed) the record processing of query A will also get reduced by same rate. So, overall query A is much better than query B.
edited by
12 12 votes

B) as  b  is very small compared to a and d which is  also taken in account also from the fact that there is a condition  b-city = "Agra" branch which already filter  city as agra making it small  and before that σbal < 0 account ⋈ depositor filter  and give selected tables so ⋈  between them will give same result and better one.
Please correct If Not also 3 and 4 are wrong as σ
b-city = "Agra"   bal < 0 account ⋈ depositor selects city from account ⋈ depositor which is not in either Schemas.

9 9 votes
I guess the most efficient one is this one:

$\prod_{c\_name}(((\sigma_{b\_city="Agra"}branch)\bowtie(\sigma_{bal<0}account))\bowtie depositor)$
 

though it is not given in the options.

Am I right @Arjun sir?
edited by
1 1 vote

When optimizing relational algebra expressions, the goal is not only logical correctness but also minimization of intermediate result sizes. This is especially critical when one relation is small and others are large. 

Instance:

$$
\texttt{branch:}
\quad
\begin{array}{|c|c|c|}
\hline
\texttt{b-name} & \texttt{b-city} & \texttt{assets} \\
\hline
B1 & \texttt{Agra} & 500 \\
B2 & \texttt{Delhi} & 600 \\
B3 & \texttt{Mumbai} & 700 \\
\hline
\end{array}
$$

$$
\texttt{account:}
\quad
\begin{array}{|c|c|c|}
\hline
\texttt{a-num} & \texttt{b-name} & \texttt{bal} \\
\hline
A1 & B1 & -100 \\
A2 & B1 & 200 \\
A3 & B1 & 300 \\
A4 & B2 & -50 \\
A5 & B2 & -60 \\
A6 & B3 & -70 \\
\hline
\end{array}
$$

$$
\texttt{depositor:}
\quad
\begin{array}{|c|c|}
\hline
\texttt{c-name} & \texttt{a-num} \\
\hline
C1 & A1 \\
C2 & A2 \\
C3 & A3 \\
C4 & A4 \\
C5 & A5 \\
C6 & A6 \\
\hline
\end{array}
$$

Correct result: Only account $A1$ is in "Agra" and has $\texttt{bal < 0}$ → output: $\{C1\}$.

Now evaluate all options.



Option A:  
$$
\Pi_{\texttt{c-name}} \left( \sigma_{\texttt{bal < 0}} \left( \sigma_{\texttt{b-city = "Agra"}}(\texttt{branch}) \bowtie \texttt{account} \right) \bowtie \texttt{depositor} \right)
$$

Steps:

  1. $\sigma_{\texttt{b-city="Agra"}}(\texttt{branch}) = \{(B1, \texttt{Agra}, 500)\}$
  2. Join with $\texttt{account}$ → accounts at B1: $A1, A2, A3$ → 3 tuples
  3. $\sigma_{\texttt{bal < 0}}$ → only $A1$ → 1 tuple
  4. Join with $\texttt{depositor}$ → $C1$
  5. Project → $\{C1\}$

Correct Result. Peak intermediate size: 3 tuples (after step 2).



Option B:  
$$
\Pi_{\texttt{c-name}} \left( \sigma_{\texttt{b-city = "Agra"}}(\texttt{branch}) \bowtie \left( \sigma_{\texttt{bal < 0}}(\texttt{account}) \bowtie \texttt{depositor} \right) \right)
$$

Steps:

  1. $\sigma_{\texttt{bal < 0}}(\texttt{account}) = \{A1, A4, A5, A6\}$ → 4 tuples
  2. Join with $\texttt{depositor}$ → $\{C1, C4, C5, C6\}$ → 4 tuples
  3. $\sigma_{\texttt{b-city="Agra"}}(\texttt{branch}) = \{(B1, \texttt{Agra}, 500)\}$
  4. Final join on $\texttt{b-name}$: only $A1$ (B1) matches → $C1$
  5. Project → $\{C1\}$

Correct Result:  Peak intermediate size: 4 tuples (after step 2).

Even in this tiny instance, Option B processes more data: 4 vs. 3 tuples. The gap widens dramatically at scale.



Option C:  
$$
\Pi_{\texttt{c-name}} \left( \left( \sigma_{\texttt{b-city = "Agra"}}(\texttt{branch}) \bowtie \sigma_{\texttt{b-city = "Agra"} \land \texttt{bal < 0}}(\texttt{account}) \right) \bowtie \texttt{depositor} \right)
$$

Selection $\sigma_{\texttt{b-city = "Agra"} \land \texttt{bal < 0}}(\texttt{account})$ is invalid: $\texttt{account}$ has no $\texttt{b-city}$.

Semantically incorrect.



Option D:  
$$
\Pi_{\texttt{c-name}} \left( \sigma_{\texttt{b-city = "Agra"}}(\texttt{branch}) \bowtie \left( \sigma_{\texttt{b-city = "Agra"} \land \texttt{bal < 0}}(\texttt{account}) \bowtie \texttt{depositor} \right) \right)
$$

Same error: $\texttt{b-city}$ not in $\texttt{account}$.

Semantically incorrect.



Scalability Insight from This Instance

In the example:

  • Agra branch has 3 accounts,
  • But 4 accounts in total have $\texttt{bal < 0}$ (including 3 outside Agra).

Thus:

  • Option A never sees the 3 non-Agra negative accounts,
  • Option B processes all 4, then discards 3 in the final join.

Now scale up:

  • Suppose 100 branches, 1,000,000 accounts,
  • Agra: 10,000 accounts,
  • Negative balance: 100,000 accounts (only 1,000 in Agra).

Then:

  • Option A intermediate after join: 10,000 → after filter: 1,000
  • Option B intermediate after filter: 100,000 → after depositor join: ~200,000
  • The 20$\times$ blowup in Option B arises directly from the pattern visible even in our small instance.


Therefore

  • Options C and D are invalid due to attribute misuse.
  • Options A and B are correct, but Option A minimizes intermediate results by using the small $\texttt{branch}$ relation to restrict $\texttt{account}$ early.
  • The constructed instance explicitly shows that Option B processes more tuples even at small scale, and this difference scales linearly with data size.

Therefore, Option A is the most efficient.

–2 –2 votes
As the conditional expression contains the comparison of attributes with constants so they can be applied independently  for filtering out some tuples  before performing the join operation over the relations because this will reduce the relation to smaller ones and join can be easily on smaller relations.

Given query is inefficient as join is performed before the selecting the tuples from the relation so we have to select the efficient query from options.

Option A have condition ( bal < 0 ) which is performed after performing join of branch and account So, inefficient.

Option C have condition ( b-city = 'agra' ) with account relation but b-city is not there in account. So, inefficient.

Option D is nearly same as C, so inefficient.

Option B is the most efficient one as filtering of tuples is performed before joining.

Therefore, Option B is correct.
Answer:
Position:
Show:

Related questions

61 61 votes
5 answers 5 answers
35.1k
35.1k views
Ishrat Jahan asked Oct 30, 2014
35,063 views
Consider the $B^{+}$ tree in the adjoining figure, where each node has at most two keys and three links.Keys $K15$ and then $K25$ are inserted into this tree in that orde...
67 67 votes
5 answers 5 answers
25.2k
25.2k views
Ishrat Jahan asked Oct 30, 2014
25,244 views
Consider the $B^+$ tree in the adjoining figure, where each node has at most two keys and three links.Keys $K15$ and then $K25$ are inserted into this tree in that order....
59 59 votes
9 answers 9 answers
22.7k
22.7k views
Ishrat Jahan asked Oct 30, 2014
22,710 views
Consider the following implications relating to functional and multivalued dependencies given below, which may or may not be correct.if $A \rightarrow \rightarrow B$ and ...
72 72 votes
8 answers 8 answers
28.7k
28.7k views
Ishrat Jahan asked Oct 30, 2014
28,697 views
Consider the following two transactions$: T1$ and $T2.$$\begin{array}{clcl} T1: & \text{read (A);} & T2: & \text{read (B);} \\ & \text{read (B);} & & \text{read (A);} \\ ...