cancel
Showing results for 
Search instead for 
Did you mean: 
Read only

WITH HINT is highly needed in SAP CAP

Petr_Plenkov
Active Participant
1,631

Dear developers,

Since we started building artifacts using cap framework quite quickly we came to performance issues.

Like for example I've created a large union of multiple events from different sources

entity events as select from source_1 {
'SOURCE_1' as source,
....
} union all select from source_2 { 
'SOURCE_2' as source,
...
}
and so on 

as a result I expect that whenever I select from such an entity, union node pruning must happen based on where source = ... condition.

However when we started testing it I've noticed such a behavior:

- if I use hardcoded values to query a view generated from such cds - pruning happens and it only selects data from one of union tables which is matching source filter

- however when handling odata request CAP generates quite generic statement

where source = ? and... and calling it with parameters.

Unfortunately for such a plan the behavior in our current Hana revision ( 2.0 rev56 ) is different and ESX engine starts pulling all the tables from the union. It dramatically increases memory and CPU consumtion, api's work poorly

So we have found a note pretty much close to the issue we face: https://launchpad.support.sap.com/#/notes/3133887

Of course there is a patch ( no fact that it will help ) but there is also immediate workaround by applying hints to the view.

So hint like NO_ESX_UNION_ALL works as expected however we cannot inject it to CDS/generated hdbview anyhow.

From our practice we have many more examples when hints were needed for some of our views therefore it would be nice if we could use them in CAP as well.

Please confirm if you have such a feature in your backlog.

Thank you!

Accepted Solutions (1)

Accepted Solutions (1)

TobiT
Participant

For everybody landing on this page, this is now possible with CAP: https://cap.cloud.sap/docs/java/query-execution#hana-hints

TiagoAlmeida
Participant
0 Kudos

Great, thanks for sharing. Is there such a thing for CAP Node.js ? I believe not 😞

Answers (1)

Answers (1)

Petr_Plenkov
Active Participant

johannesvogel so far here is my implementation of this feature:

odata.js

const cds = require("@sap/cds");
const enableHints = require("./pulgins/enable_hints");

cds
  .connect("db")
  .then(({ db }) =>
    db?.before("READ", (req) => enableHints(req)      
    )
  );

module.exports = class odata {};

and enable_hints.js

const SelectBuilder = require("@sap/cds/libx/_runtime/db/sql-builder/SelectBuilder");
const { build } = SelectBuilder.prototype;

// with hint support
Object.assign(SelectBuilder.prototype, {
  build() {
    const result = build.apply(this, arguments);

    // to support also expands we will proxy all found hints to the end of the query
    const hintsRegex = /(?<=WITH HINT\().*?(?=\))/g;
    const foundHints = [result.sql.match(hintsRegex)]
      .flat()
      .filter((hints) => hints)
      .flatMap((hints) => hints.split(","));
    if (!this._obj.SELECT.withHint) {
      this._obj.SELECT.withHint = foundHints;
      // remove current hints to avoid duplicate definition
      result.sql = result.sql.replace(/(WITH HINT\().*?(\))/g, "");
    }

    if (
      Array.isArray(this._obj.SELECT.withHint) &&
      this._obj.SELECT.withHint.length
    ) {
      this._withHint(result);
    }

    return result;
  },
  _withHint(result) {
    result.sql = result.sql.concat(
      ` WITH HINT(${this._obj.SELECT.withHint.join(",")})`
    );
  },
});

// query handler
module.exports = function enableHints({ target, query }) {
  const withHint = target["@Consumption.dbHints"];
  Array.isArray(withHint) && Object.assign(query.SELECT, { withHint });
};
I know it's kind of a hacky way to do this, but it works as a concept just perfectly. So now we are able to have a model like this

and it injects this hint not only to direct selects but also to quite deep navigations. So I've solved some issue which I've been trying to solve during couple weeks 😃

johannesvogel
Product and Topic Expert
Product and Topic Expert
0 Kudos

Hi,

sorry for my late response.

As you already state, it's a hacky solution that uses internal information.

I'm happy if that solves your problem but be aware that this might break with future releases.

When implementing this feature in general, we'll strive for an ABAP independent solution.

Best regards,

Johannes

akuller
Participant
0 Kudos
Hi @johannesvogel is there anything new to the standard solution yet?
johannesvogel
Product and Topic Expert
Product and Topic Expert
0 Kudos
akuller
Participant
0 Kudos
Hi @johannesvogel unfortunately this is only cql. How can I use this on a projection with the generic provider? Yes, it is possible, but it would be elegant to specify this directly in a view or in the package.json.
johannesvogel
Product and Topic Expert
Product and Topic Expert
0 Kudos
There's no annotation nor a cds configuration to specify which hints to be used. I think this makes it too prone to misconfiguration. Hints should be used with care when really needed.
akuller
Participant
0 Kudos
Hi @johannesvogel the setting in the package json would affect the engine selection. this can be configured in s4, see note https://me.sap.com/notes/2570371#L5. I would like to have individual hints for a view, why should I build a separate handler for it if it could also be annotated in the view. Analogous to the cds views in s4.
AbhishekMallik
Newcomer
0 Kudos

Hi @Petr_Plenkov,

We have a similar use case with big unions and virtual tables and currently use CAP v8. I am going to dig into the framework to try implement this with CAP v8.
My only query is that is the file odata.js a service handler that intercepts all db calls?
Also, have you tried with a recent CAP version. We really need this feature as annotations on the service entities to optimize the query performance.

BR,

Abhishek