Subject | Re: Optimizing a subquery |
---|---|
Author | Adam |
Post date | 2006-07-13T23:28:10Z |
--- In firebird-support@yahoogroups.com, "Ann W. Harrison"
<aharrison@...> wrote:
optimise it:
PLAN (CUSTOMERS NATURAL)
PLAN (CUSTOMERS NATURAL)
A quick experiment with my tables shows that there are
n * (n + 1) reads
where n is the number of records in CUSTOMERS
kokok_kokok,
The easiest way to handle this in a single statement is to create a
selectable stored procedure.
CREATE OR ALTER PROCEDURE MYPROC
RETURNS
(
CUSTOMERID BIGINT
SALES NUMERIC(15,4),
TOTAL NUMERIC(15,4)
)
AS
BEGIN
select COALESCE(sum(Sales), 0)
from Customers
INTO :TOTAL;
FOR select CustomerId, Sales
from Customers
INTO :CUSTOMERID, :SALES
DO
BEGIN
SUSPEND;
END
END
^
Then you can run
SELECT CUSTOMERID, SALES, TOTAL
FROM MYPROC;
This should return the results with 2*n reads for customer, which is
more efficient than the first query as soon as you have more than 2
records in your Customers table.
Adam
<aharrison@...> wrote:
>It possibly has been improved since, but 1.5.3 does not appear to
> kokok_kokok wrote:
> >
> > I need to do:
> >
> > select CustomerId, Sales, (select sum(Sales) from Customers) as Total
> > from Customers
> >
> > It works fine, but for each row, Firebird executes the subquery
> > "select sum(Sales) from Customers".
> >
>
> Are you sure? At one time, I'm quite sure that the compiler/optimizer
> were good enough to remove loop invariants.
>
optimise it:
PLAN (CUSTOMERS NATURAL)
PLAN (CUSTOMERS NATURAL)
A quick experiment with my tables shows that there are
n * (n + 1) reads
where n is the number of records in CUSTOMERS
kokok_kokok,
The easiest way to handle this in a single statement is to create a
selectable stored procedure.
CREATE OR ALTER PROCEDURE MYPROC
RETURNS
(
CUSTOMERID BIGINT
SALES NUMERIC(15,4),
TOTAL NUMERIC(15,4)
)
AS
BEGIN
select COALESCE(sum(Sales), 0)
from Customers
INTO :TOTAL;
FOR select CustomerId, Sales
from Customers
INTO :CUSTOMERID, :SALES
DO
BEGIN
SUSPEND;
END
END
^
Then you can run
SELECT CUSTOMERID, SALES, TOTAL
FROM MYPROC;
This should return the results with 2*n reads for customer, which is
more efficient than the first query as soon as you have more than 2
records in your Customers table.
Adam