SQL Tip: Avoid Applying Functions to Table Data

One of the top SQL tips on many lists for developers of SQL is to avoid applying a function to the table data. I think of this as avoiding funcitons on the left of my comparison operator (=, !=, >, <, etc) – though that’s a simplification that may not always be correct.

The main reason to avoid this is because DB2 cannot make use of an index for a function like that. In DB2 10.5, you may be able to use an expression-based index to alleviate this when it is unavoidable, but you cannot reasonably create an index for every possible function. Especially in e-commerce databases, we need to keep indexing to a minimum. I would reserve that for critical queries where you cannot avoid a function or expression on a table column.

Real World Example

This is a precept in writing high-performing queries, and one I have readily repeated when asked about SQL performance. But when I was recently working on a reporting query that was intended to run against a WebSphere Commerce database, I tried the query both ways to see what difference it really made. The results were astounding – with the recommended syntax, the otherwise identical query ran nearly 45% faster.

The only change between two explains of a query was altering this clause:

date(o.timeplaced) = current date - 1 day

to this:

o.timeplaced between timestamp(current date - 1 day,'00.00.00') and timestamp(current date - 1 day,'23.59.59')

Warning – the explain plans were done before further optimization, so are a bit ugly – also this is a complicated query – the developers rarely engage a DBA for the simple ones. The explain plan for the first, less efficient method was this:

Access Plan:
-----------
    Total Cost:         216.313
    Query Degree:       1

                                                                                                                                                                                    Rows 
                                                                                                                                                                                   RETURN
                                                                                                                                                                                   (   1)
                                                                                                                                                                                    Cost 
                                                                                                                                                                                     I/O 
                                                                                                                                                                                     |
                                                                                                                                                                                 7.07267e-08 
                                                                                                                                                                                  >^NLJOIN
                                                                                                                                                                                  (   2)
                                                                                                                                                                                   216.313 
                                                                                                                                                                                   110.842 
                                                                                                                                                              /----------------------+-----------------------\
                                                                                                                                                        7.07267e-08                                             1 
                                                                                                                                                          FILTER                                             FETCH 
                                                                                                                                                          (   3)                                             (  28)
                                                                                                                                                          201.17                                             22.7039 
                                                                                                                                                          108.841                                            3.00042 
                                                                                                                                                            |                                              /---+----\
                                                                                                                                                        0.00824711                                        1         276276 
                                                                                                                                                         >^NLJOIN                                      IXSCAN   TABLE: WSCOMUSR
                                                                                                                                                         (   4)                                        (  29)      CATENTRY
                                                                                                                                                          201.17                                       15.1372        Q1
                                                                                                                                                          108.841                                         2 
                                                                                                                                /---------------------------+---------------------------\                |
                                                                                                                          0.00824711                                                       1           276276 
                                                                                                                            >NLJOIN                                                     FETCH      INDEX: SYSIBM  
                                                                                                                            (   5)                                                      (  26)   SQL120207194339220
                                                                                                                            186.027                                                     22.7039          Q1
                                                                                                                            106.841                                                     3.00042 
                                                                                                   /--------------------------+--------------------------\                            /---+----\
                                                                                             0.00824711                                                     1                        1         276276 
                                                                                               >NLJOIN                                                   FETCH                    IXSCAN   TABLE: WSCOMUSR
                                                                                               (   6)                                                    (  24)                   (  27)      CATENTRY
                                                                                               170.855                                                   15.1716                  15.1372        Q16
                                                                                               104.838                                                   2.0025                      2 
                                                                       /-------------------------+-------------------------\                           /---+---\                    |
                                                                 0.00824711                                               0.406433                    1        276274             276276 
                                                                   >NLJOIN                                                 FETCH                   IXSCAN  TABLE: WSCOMUSR    INDEX: SYSIBM  
                                                                   (   7)                                                  (  22)                  (  25)    CATENTDESC     SQL120207194339220
                                                                   160.207                                                 10.648                  7.5892        Q14                Q16
                                                                   103.432                                                 1.40643                    1 
                                              /----------------------+-----------------------\                           /---+----\                  |
                                        0.00800992                                           1.02961                0.406433       2148            276274 
                                          >NLJOIN                                            FETCH                   IXSCAN   TABLE: WSCOMUSR  INDEX: WSCOMUSR
                                          (   8)                                             (  20)                  (  23)     OICOMPLIST        I0001248
                                          144.966                                            15.2419                 7.57382        Q12              Q14
                                          101.418                                            2.01364                    1 
                          /-----------------+------------------\                           /---+----\                  |
                    0.00800992                                0.134035                 1.02961       5285             2148 
                     >^NLJOIN                                  FETCH                   IXSCAN   TABLE: WSCOMUSR  INDEX: WSCOMUSR
                     (   9)                                    (  18)                  (  21)     ORDERITEMS        I0000301
                      136.378                                  8.58738                 7.57522        Q10              Q12
                      100.284                                  1.13403                    1 
               /--------+--------\                           /---+----\                  |
         0.00800992                 1                   0.134035        688             5285 
           TBSCAN                FETCH                   IXSCAN   TABLE: WSCOMUSR  INDEX: WSCOMUSR
           (  10)                (  16)                  (  19)     ORDPROMOCD         I172138
           121.045               15.3337                 7.57342        Q8               Q10
           98.2582               2.02592                    1 
             |                 /---+----\                  |
         0.00800992           1          4051              688 
           SORT            IXSCAN   TABLE: WSCOMUSR  INDEX: WSCOMUSR
           (  11)          (  17)       ADDRESS         I0000418
           121.044         7.57419        Q6               Q8
           98.2582            1 
             |               |
         0.00800992         4051 
           FETCH       INDEX: SYSIBM  
           (  12)    SQL120207194329140
           121.044           Q6
           98.2582 
         /---+----\
       934         5133 
     RIDSCN   TABLE: WSCOMUSR
     (  13)       ORDERS
     17.1415        Q4
     2.18352 
       |
       934 
     SORT  
     (  14)
     17.1412 
     2.18352 
       |
       934 
     IXSCAN
     (  15)
     16.9044 
     2.18352 
       |
      5133 
 INDEX: WSCOMUSR
    I0000654
       Q4

The detail on the operator where the predicate is applied looks like this:

        12) FETCH : (Fetch)
                Cumulative Total Cost:          121.044
                Cumulative CPU Cost:            5.38439e+06
                Cumulative I/O Cost:            98.2582
                Cumulative Re-Total Cost:       0.931069
                Cumulative Re-CPU Cost:         3.94233e+06
                Cumulative Re-I/O Cost:         0
                Cumulative First Row Cost:      120.94
                Estimated Bufferpool Buffers:   85.5416

                Arguments:
                ---------
                MAX RIDS: (Maximum RIDs per list prefetch request)
                        623
                PREFETCH: (Type of Prefetch)
                        LIST
                ROWLOCK : (Row Lock intent)
                        NONE
                SPEED   : (Assumed speed of scan, in sharing structures)
                        SLOW
                TABLOCK : (Table Lock intent)
                        INTENT NONE
                TBISOLVL: (Table access Isolation Level)
                        UNCOMMITTED READ
                THROTTLE: (Scan may be throttled, for scan sharing)
                        FALSE
                VISIBLE : (May be included in scan sharing structures)
                        FALSE
                WRAPPING: (Scan may start anywhere and wrap)
                        FALSE

                Predicates:
                ----------
                14) Sargable Predicate,
                        Comparison Operator:            Equal (=)
                        Subquery Input Required:        No
                        Filter Factor:                  0.18196

                        Predicate Text:
                        --------------
                        (Q4.STOREENT_ID = 12001)


                15) Sargable Predicate,
                        Comparison Operator:            In List (IN), evaluated by binary search (list sorted at compile-time)
                        Subquery Input Required:        No
                        Filter Factor:                  0.0440203

                        Predicate Text:
                        --------------
                        Q4.STATUS IN ('C', 'D', 'M', 'R', 'S')


                16) Sargable Predicate,
                        Comparison Operator:            Equal (=)
                        Subquery Input Required:        No
                        Filter Factor:                  0.000194818

                        Predicate Text:
                        --------------
                        (DATE(Q4.TIMEPLACED) = $C0)



                Input Streams:
                -------------
                        4) From Operator #13

                                Estimated number of rows:       934
                                Number of columns:              1
                                Subquery predicate ID:          Not Applicable

                                Column Names:
                                ------------
                                +Q4.$RID$(A)

                        5) From Object WSCOMUSR.ORDERS

                                Estimated number of rows:       5133
                                Number of columns:              9
                                Subquery predicate ID:          Not Applicable

                                Column Names:
                                ------------
                                +Q4.TOTALADJUSTMENT+Q4.ADDRESS_ID+Q4.STATUS
                                +Q4.TIMEPLACED+Q4.STOREENT_ID+Q4.TOTALSHIPPING
                                +Q4.TOTALTAX+Q4.TOTALPRODUCT+Q4.ORDERS_ID


                Output Streams:
                --------------
                        6) To Operator #11

                                Estimated number of rows:       0.00800992
                                Number of columns:              8
                                Subquery predicate ID:          Not Applicable

                                Column Names:
                                ------------
                                +Q5.TOTALSHIPPING+Q5.TOTALTAX
                                +Q5.TOTALADJUSTMENT+Q5.TOTALPRODUCT+Q5.STATUS
                                +Q5.TIMEPLACED+Q5.ORDERS_ID+Q5.ADDRESS_ID

The explain plan for the second, more efficient method was this:

Access Plan:
-----------
    Total Cost:         120.626
    Query Degree:       1

                                                                                                                                                                          Rows 
                                                                                                                                                                         RETURN
                                                                                                                                                                         (   1)
                                                                                                                                                                          Cost 
                                                                                                                                                                           I/O 
                                                                                                                                                                           |
                                                                                                                                                                       7.5497e-05 
                                                                                                                                                                        >^NLJOIN
                                                                                                                                                                        (   2)
                                                                                                                                                                         120.626 
                                                                                                                                                                         15.9328 
                                                                                                                                                                  /--------+--------\
                                                                                                                                                            7.5497e-05                 1 
                                                                                                                                                              TBSCAN                FETCH 
                                                                                                                                                              (   3)                (  26)
                                                                                                                                                              105.483               22.7039 
                                                                                                                                                              13.9323               3.00042 
                                                                                                                                                                |                 /---+----\
                                                                                                                                                            7.5497e-05           1         276276 
                                                                                                                                                              SORT            IXSCAN   TABLE: WSCOMUSR
                                                                                                                                                              (   4)          (  27)      CATENTRY
                                                                                                                                                              105.483         15.1372        Q1
                                                                                                                                                              13.9323            2 
                                                                                                                                                                |               |
                                                                                                                                                            7.5497e-05        276276 
                                                                                                                                                              FILTER      INDEX: SYSIBM  
                                                                                                                                                              (   5)    SQL120207194339220
                                                                                                                                                              105.482           Q1
                                                                                                                                                              13.9323 
                                                                                                                                                                |
                                                                                                                                                             0.147583 
                                                                                                                                                             >^NLJOIN
                                                                                                                                                             (   6)
                                                                                                                                                              105.482 
                                                                                                                                                              13.9323 
                                                                                                                                    /---------------------------+---------------------------\
                                                                                                                               0.147583                                                        1 
                                                                                                                                >NLJOIN                                                     FETCH 
                                                                                                                                (   7)                                                      (  24)
                                                                                                                                90.3387                                                     22.7039 
                                                                                                                                11.9319                                                     3.00042 
                                                                                                       /--------------------------+--------------------------\                            /---+----\
                                                                                                  0.147583                                                      1                        1         276276 
                                                                                                   >NLJOIN                                                   FETCH                    IXSCAN   TABLE: WSCOMUSR
                                                                                                   (   8)                                                    (  22)                   (  25)      CATENTRY
                                                                                                   75.1671                                                   15.1716                  15.1372        Q16
                                                                                                   9.92941                                                   2.0025                      2 
                                                                           /-------------------------+-------------------------\                           /---+---\                    |
                                                                      0.147583                                                0.406433                    1        276274             276276 
                                                                       >NLJOIN                                                 FETCH                   IXSCAN  TABLE: WSCOMUSR    INDEX: SYSIBM  
                                                                       (   9)                                                  (  20)                  (  23)    CATENTDESC     SQL120207194339220
                                                                       64.5191                                                 10.648                  7.5892        Q14                Q16
                                                                       8.52297                                                 1.40643                    1 
                                                 /-----------------------+-----------------------\                           /---+----\                  |
                                            0.143338                                             1.02961                0.406433       2148            276274 
                                             >NLJOIN                                             FETCH                   IXSCAN   TABLE: WSCOMUSR  INDEX: WSCOMUSR
                                             (  10)                                              (  18)                  (  21)     OICOMPLIST        I0001248
                                             49.2773                                             15.2419                 7.57382        Q12              Q14
                                             6.50934                                             2.01364                    1 
                            /------------------+-------------------\                           /---+----\                  |
                       0.143338                                   0.134035                 1.02961       5285             2148 
                       >^NLJOIN                                    FETCH                   IXSCAN   TABLE: WSCOMUSR  INDEX: WSCOMUSR
                       (  11)                                      (  16)                  (  19)     ORDERITEMS        I0000301
                        40.6899                                    8.58738                 7.57522        Q10              Q12
                        5.3753                                     1.13403                    1 
               /----------+----------\                           /---+----\                  |
          0.143338                      1                   0.134035        688             5285 
           FETCH                     FETCH                   IXSCAN   TABLE: WSCOMUSR  INDEX: WSCOMUSR
           (  12)                    (  14)                  (  17)     ORDPROMOCD         I172138
           25.3562                   15.3337                 7.57342        Q8               Q10
           3.34938                   2.02592                    1 
         /---+----\                /---+----\                  |
     17.8951       5133           1          4051              688 
     IXSCAN   TABLE: WSCOMUSR  IXSCAN   TABLE: WSCOMUSR  INDEX: WSCOMUSR
     (  13)       ORDERS       (  15)       ADDRESS         I0000418
     7.58131        Q4         7.57419        Q6               Q8
        1                         1 
       |                         |
      5133                      4051 
 INDEX: WSCOMUSR           INDEX: SYSIBM  
     I173124             SQL120207194329140
       Q4                        Q6

Details on the operator where this particular predicate is applied look like this:

        13) IXSCAN: (Index Scan)
                Cumulative Total Cost:          7.58131
                Cumulative CPU Cost:            90214.1
                Cumulative I/O Cost:            1
                Cumulative Re-Total Cost:       0.00986093
                Cumulative Re-CPU Cost:         41753.1
                Cumulative Re-I/O Cost:         0
                Cumulative First Row Cost:      7.57403
                Estimated Bufferpool Buffers:   2

                Arguments:
                ---------
                MAXPAGES: (Maximum pages for prefetch)
                        1
                PREFETCH: (Type of Prefetch)
                        NONE
                ROWLOCK : (Row Lock intent)
                        NONE
                SCANDIR : (Scan Direction)
                        FORWARD
                TABLOCK : (Table Lock intent)
                        INTENT NONE
                TBISOLVL: (Table access Isolation Level)
                        UNCOMMITTED READ

                Predicates:
                ----------
                16) Stop Key Predicate,
                        Comparison Operator:            Less Than or Equal (<=)
                        Subquery Input Required:        No
                        Filter Factor:                  0.0116209

                        Predicate Text:
                        --------------
                        (Q4.TIMEPLACED <= TIMESTAMP((CURRENT DATE - 1 DAYS),
                                '23.59.59.999999'))


                17) Start Key Predicate,
                        Comparison Operator:            Less Than or Equal (<=)
                        Subquery Input Required:        No
                        Filter Factor:                  0.0116209

                        Predicate Text:
                        --------------
                        (TIMESTAMP((CURRENT DATE - 1 DAYS),
                                '00.00.00.000000') <= Q4.TIMEPLACED)



                Input Streams:
                -------------
                        1) From Object WSCOMUSR.I173124

                                Estimated number of rows:       5133
                                Number of columns:              2
                                Subquery predicate ID:          Not Applicable

                                Column Names:
                                ------------
                                +Q4.TIMEPLACED(A)+Q4.$RID$


                Output Streams:
                --------------
                        2) To Operator #12

                                Estimated number of rows:       17.8951
                                Number of columns:              2
                                Subquery predicate ID:          Not Applicable

                                Column Names:
                                ------------
                                +Q4.TIMEPLACED(A)+Q4.$RID$

Basically, in the less efficient method, the date predicate is applied during the FETCH from the orders table, accounting for the vast majority of timerons in that step (nearly 100). In the more efficient method, we can see that an index is insted used before the fetch from the orders table, vastly reducing the cost of that fetch.

If we look at that FETCH operator for the ORDERS table at the far lower left in each plan, we can also see that DB2 has to do less I/O - estimating ~3.3 I/Os instead of ~98.

This is an example of the drastic difference that it makes to apply functions in the optimal place. This particular query is only slated to run daily, so I'm not terribly worried about 100 timerons, but it was fun to experiment and prove one of the precepts of good SQL right.

Ember Crooks
Ember Crooks

Ember is always curious and thrives on change. She has built internationally recognized expertise in IBM Db2, spent a year working with high-volume MySQL, and is now learning Snowflake. Ember shares both posts about her core skill sets and her journey learning Snowflake.

Ember lives in Denver and work from home

Articles: 548

4 Comments

  1. Love it when I read “left of my comparison operator”.
    I also code: [code]
    select lastname from employee a where a.firstnme = ‘JOHN’ [/code]
    But sometimes I see SQL like this: [code]
    select lastname from employee a where ‘JOHN’ = a.firstnme[/code]
    It looks very odd to me, but it seems to work as well. I never found arguments why the db-column should be on the left…. Are there?

    • Hi Dick,

      the ‘other way round’ is mostly a coding pattern to prevent unintentional assignment, when there is an assignment operator ‘=’ and a comparison operator ‘==’. Some people do it even here… 😉

      Cheers
      Roland

Leave a Reply to BobbyCancel Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.