1

My task is to optimize this query:

Declare @sumBalance NUMERIC = (select SUM(CURRENT_BALANCE) as Balance
from dbo.ACCOUNT_DETAILS)
select @sumBalance

I've read that the best solution for aggregation functions is using indexed views instead of tables.

I've created the view with SCHEMABINDING:

CREATE VIEW dbo.CURRENT_BALANCE_VIEW
WITH SCHEMABINDING
AS
    SELECT id,CURRENT_BALANCE
    FROM dbo.ACCOUNT_DETAILS

After that I've created 2 indexes:

The first for ID

 CREATE UNIQUE CLUSTERED INDEX index_ID_VIEW ON dbo.View(ID);

The second for CURRENT_BALANCE my second one column

CREATE NONCLUSTERED INDEX index_CURRENT_BALANCE_VIEW
ON dbo.CURRENT_BALANCE_VIEW(ID);

And here I got troubles with new query:

Declare @sumBalance NUMERIC = (select SUM(CURRENT_BALANCE) as Balance
from dbo.CURRENT_BALANCE_VIEW)
select @sumBalance
  1. New query doesn't use view

    https://i.stack.imgur.com/jlPEd.png

  2. Somehow my indexes were added to the folder Statistics

    Look in another post

  3. I don't understand why I can see index 'index_current_balance' cause there is no such an index in the table

Look in another post

P.S. Already tried create index in the table and it helped. It made query works faster from 0.2 Es.operator cost to 0.009 but anyway it must be faster.

p.s.s Sorry for making you click on the link, my reputation doesn't allow me to past images properly =\

p.s.s.s Working with SQL Server 2014

p.s.s.s.s Just realized that I don't need to sum 0-s. Expected them grom function.

Thanks in advance.

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
S. Elmar
  • 23
  • 5

2 Answers2

2

if you use Standard Edition of SQL-Server you have to use the NOEXPAND-Hint in order to use the index of a view.

For example:

SELECT *
FROM dbo.CURRENT_BALANCE_VIEW (NOEXPAND);
CPMunich
  • 725
  • 4
  • 13
1

This query:

Declare @sumBalance NUMERIC = (select SUM(CURRENT_BALANCE) as Balance
                               from dbo.ACCOUNT_DETAILS);
select @sumBalance;

is not easy to optimize. The only index that will help it is:

create index idx_account_details_current_balance on account_details(current_balance);

This is a covering index for the query, and can be used for the SUM(). However, the index still needs to be scanned to do the SUM(). Scanning the index should be faster than scanning the table because it is likely to be much smaller.

SQL Server 2012+ has a facility called columnstore indexes that would have the same effect.

The advice for using indexed views for aggregation functions doesn't seem like good advice. For instance, if the above query used MIN() or MAX(), then the above index should be the optimal index for the query, and it should run quite fast.

EDIT:

Your reference article is quite reasonable. If you want to create an indexed view for this purpose, then create it with aggregation.

CREATE VIEW dbo.CURRENT_BALANCE_VIEW
WITH SCHEMABINDING
AS
    SELECT SUM(CURRENT_BALANCE) as bal, COUNT_BIG(CURRENT_BALANCE) as cnt
    FROM dbo.ACCOUNT_DETAILS;

This is a little weird, because it returns one row. I think the following will work:

create index idx_account_details on current_balance_view(bal);

If not, you may need to introduce a dummy column for the index.

Then:

select *
from dbo.current_balance_view;

should have the precomputed value.

Gordon Linoff
  • 1,242,037
  • 58
  • 646
  • 786
  • Thanks for advice. As i already said index increased speed in 22.2 times, but anyway i need it to be faster, at least 100-500 times. Info about views i 've got from here https://www.simple-talk.com/sql/learn-sql-server/sql-server-indexed-views-the-basics/ – S. Elmar Nov 13 '15 at 12:02
  • May i ask you to answer questions from 1 to 3 in my post, please. I can't found anything explaining me why it happens. – S. Elmar Nov 13 '15 at 12:04
  • Going to try columnstore indexes as you adviced. – S. Elmar Nov 13 '15 at 12:07
  • Unfortunatly I cant use columnstore because: CREATE INDEX statement failed because a columnstore index cannot be created in this edition of SQL Server. See Books Online for more details on feature support in different SQL Server editions. – S. Elmar Nov 13 '15 at 12:29
  • Then trying to create index for the dummy column of ids there is an error: Cannot create index on view 'MFS_DEMO_IT.dbo.CURRENT_BALANCE_VIEW' because its select list does not include a proper use of COUNT_BIG. Consider adding COUNT_BIG(*) to select list. – S. Elmar Nov 17 '15 at 09:18