A method for improving performance of join operations, the method comprising: building a directed graph based on a schema of a database, the directed graph comprising vertices and edges, wherein the vertices represent tables in the schema and each edge between a pair of vertices represents a directed relationship comprising a join condition between the tables represented by the pair of vertices; traversing the directed graph to determine a plurality of N potential denormalizations, wherein the plurality of N potential denormalizations are each represented by a subgraph of the directed graph; determining a plurality of costs M for the plurality of N potential denormalizations, wherein each cost M ( j) of the plurality of costs M is based on an amount of memory that a potential denormalization uses; determining a plurality of benefits B for the plurality of N potential denormalizations, wherein each benefit B ( j) of the plurality of benefits B is based on the cost of a join that would otherwise have been performed without the potential denormalization; initializing an array S of sets of selected denormalizations S ( i,j) and an array T of total benefits T ( i,j); performing an outer loop which steps through indexes j of current potential denormalizations, and an inner loop which steps through current amounts i of available memory up to a maximum total amount L of available memory, said performing comprising, within the inner loop: testing if (i) the cost M ( j) of the current potential denormalization is greater than the current amount i of available memory, or (ii) the previous total benefit T ( i,j -1) is greater than the sum T ( i-M ( j), j -1) + B ( j); if at least one of conditions (i) or (ii) is fulfilled, then setting the current total benefit T ( i,j) to the previous total benefit T ( i,j -1), and setting the current set of selected denormalizations S ( i,j) to the previous set of selected denormalizations S ( i,j -1); and if neither condition (i) nor condition (ii) is fulfilled, then setting the current total benefit T ( i,j) to the sum T ( i-M ( j), j -1) + B ( j), and setting the current set of selected denormalizations S ( i,j) to the set obtained from the set S ( i-M ( j), j -1) by including the denormalization having index j; and selecting, from the plurality of N potential denormalizations, the set S ( L,N) of selected denormalizations for residing in memory based on the maximum total amount L of available memory. building a directed graph based on a schema of a database, the directed graph comprising vertices and edges, wherein the vertices represent tables in the schema and each edge between a pair of vertices represents a directed relationship comprising a join condition between the tables represented by the pair of vertices; traversing the directed graph to determine a plurality of N potential denormalizations, wherein the plurality of N potential denormalizations are each represented by a subgraph of the directed graph; determining a plurality of costs M for the plurality of N potential denormalizations, wherein each cost M ( j) of the plurality of costs M is based on an amount of memory that a potential denormalization uses; determining a plurality of benefits B for the plurality of N potential denormalizations, wherein each benefit B ( j) of the plurality of benefits B is based on the cost of a join that would otherwise have been performed without the potential denormalization; initializing an array S of sets of selected denormalizations S ( i,j) and an array T of total benefits T ( i,j); performing an outer loop which steps through indexes j of current potential denormalizations, and an inner loop which steps through current amounts i of available memory up to a maximum total amount L of available memory, said performing comprising, within the inner loop: testing if (i) the cost M ( j) of the current potential denormalization is greater than the current amount i of available memory, or (ii) the previous total benefit T ( i,j -1) is greater than the sum T ( i-M ( j), j -1) + B ( j); if at least one of conditions (i) or (ii) is fulfilled, then setting the current total benefit T ( i,j) to the previous total benefit T ( i,j -1), and setting the current set of selected denormalizations S ( i,j) to the previous set of selected denormalizations S ( i,j -1); and if neither condition (i) nor condition (ii) is fulfilled, then setting the current total benefit T ( i,j) to the sum T ( i-M ( j), j -1) + B ( j), and setting the current set of selected denormalizations S ( i,j) to the set obtained from the set S ( i-M ( j), j -1) by including the denormalization having index j; and testing if (i) the cost M ( j) of the current potential denormalization is greater than the current amount i of available memory, or (ii) the previous total benefit T ( i,j -1) is greater than the sum T ( i-M ( j), j -1) + B ( j); if at least one of conditions (i) or (ii) is fulfilled, then setting the current total benefit T ( i,j) to the previous total benefit T ( i,j -1), and setting the current set of selected denormalizations S ( i,j) to the previous set of selected denormalizations S ( i,j -1); and if neither condition (i) nor condition (ii) is fulfilled, then setting the current total benefit T ( i,j) to the sum T ( i-M ( j), j -1) + B ( j), and setting the current set of selected denormalizations S ( i,j) to the set obtained from the set S ( i-M ( j), j -1) by including the denormalization having index j; and selecting, from the plurality of N potential denormalizations, the set S ( L,N) of selected denormalizations for residing in memory based on the maximum total amount L of available memory.