1

Let's say I have three tables

TRANSACTIONS

  • amount
  • date

RECORDS

  • amount
  • date

CUSTOM_RECORDS

  • amount
  • date

(Let's just say there are many other fields to justify splitting of these tables)

To calculate running balance I have two methods

-------------METHOD 1 -------------

Heavy on READ, Light on WRITE

Whenever we read, just join the table, sort by date and calculate the running balance.

PRO

  • Write is easy, just write into each table

CON

  • Reading is very heavy, the calculation needs to be done on each read. It is very strange to be querying (from let's say a span of 1 week) and to have the calculation done for ALL the records. If I query for 10 records then calculation needs to be done for 1 million records to be able to know the 10 record balance.

-------------METHOD 2 -------------

Heavy on WRITE, Light on READ

I have another table

FINAL_TABLE

  • date
  • amount
  • running balance

Whenever I write, I refresh this table and calculate all the running balance again.

PRO

  • Read is easy, running balance already computed.
  • Querying between time period is as easy as extracting the date between the time span from the FINAL_TABLE

CON

  • Write is really slow, each write on any of the Three tables mean refreshing a whole FINAL_TABLE table!

Why didn't I just reuse the latest running balance? This can occur if the entry is a guarantee to be chronological in real life. However, sometimes entry might be added late.

Currently, I am using Method 2 and every time a client save/update a row into any of the three tables, the server freeze as it tries to refresh and compute the FINAL_TABLE. Obviously, this is not very scalable.

Method 1 is also not very scalable in term of querying. I would have to calculate running balance from the beginning of time in order to know the running balance of last week.

Both Method is not very scalable. What is a good design to ensure scalability and relatively fast performance on READ and WRITE? What method does the bank use to keep track of running balance?

Pathik Vejani
  • 4,263
  • 8
  • 57
  • 98
Zanko
  • 4,298
  • 4
  • 31
  • 54

1 Answers1

1

It depends.

Suppose you have a report like transaction report where accounts' running balance will be shown. If you want to show real time data then always method 1 will be preferable. And I will suggest to use Quirky Update for this rather than using cursors, loops, sub-queries or recursions.

On the other hand, if you don't need real time running total then you could have use method 2 with a little customization. I will not support updating Final Table while you made a transaction. Rather than I will suggest to update it with interval schedule. Depending on your traffic or load you may update the running total after a interval.

And for real time I will discourage using method 2 as it will make your transaction costly.

To make your method 1 faster here is some link.

Calculating Running Total

Quirky Update

Quirky Update Performance

Halloween Protection

Create Table AccBalance
(
    AccountNO PK,
    Balance
)

Create Table AccDateWiseCumBalance
(
    AccountNO PK,
    SystemDate PK,
    Cumulative Balance
)

First table will be updated by each transaction will keep real time balance but not any history.

Second table keep account and date wise cumulative balance which will be updated at each day end.

So if you need up to previous date cumulative balance you will retrieve data from second table.

And if you need up to current date cumulative balance you will retrieve data from second table up to day before current date and retrieve current date data from first table.

Community
  • 1
  • 1
Esty
  • 1,882
  • 3
  • 17
  • 36
  • Hi, thank you for your response! The problem method 1 has is that what if you query `transaction report` for last week? Don't you have to calculate all of the rows just so you get your last week report? – Zanko Jan 11 '17 at 05:33
  • For this scenario we use both methods. In our system we keep both methods. I am updating my answer for this. – Esty Jan 11 '17 at 05:38
  • thanks for the help! One more question will it be more complicated if I were to add another field call customerID to the CumulativeBalance table. So the table will hold many customers cumulative data. I will read up on the quirky update and those stuff fully when I get back from work! Thanks. I want to clarify something, you stated that "real time data then always method 1 will be preferable with QUIRKY UPDATE". My method 1 does not have any additional table, what am I updating exactly? Thanks! – Zanko Jan 11 '17 at 07:00
  • I would suggest to make different table to keep date wise cumulative balance by customer ID like (`CustomerID`, `SystemOpenDate`, `CumulativeBalance`). – Esty Jan 11 '17 at 08:28
  • And for method 1 you are not using any tables. But if you do e.g. in my solution a temp table was used for internal calculation where I used quirky update. If you don't use any tables means you are making output by direct select then obviously you can't use that. I will suggest to use window functions for that. What I meant that running total by window functions or quirky update is always give you better performance than loop, cursor, sub quires or CLRs. – Esty Jan 11 '17 at 08:31
  • Another idea about your customer ID and Date wise cumulative balance. If your customer ID balance for a date equal to summation of accounts' balance owned by that customer for that date then one table will be suffice e.g. (`AccountNO`, `SystemOpenDate`, `CumulativeBalance` ) and you may have already a table like (`CustomerID`, `AccountNO`). You could make a `JOIN` with `SUM` to get date wise customers cumulative balance. It would be smarter than keeping another table for customers date wise cumulative balance. – Esty Jan 11 '17 at 08:38
  • Thank you so much! It will take me some times to digest all the information here. I am still a little confuse on your last suggestion haha. – Zanko Jan 11 '17 at 09:01
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/132886/discussion-between-esty-and-zanko). – Esty Jan 11 '17 at 09:02