1. A method comprising: populating in volatile memory, at least one table of two tables, based on a partition key; receiving a query that joins the two tables on a join key that is the same as the partition key; based on the query received, determining whether to use full or partial partition-wise join for the query; based on how the two tables are populated in-memory, generating a first cost estimate for a first query execution plan, of a plurality of query execution plans, that divides the query that joins the two tables into a plurality of partition-wise joins, each partition-wise join, of the plurality of partition-wise joins, between a pair of corresponding partitions from the two tables; generating a second cost estimate for a second query execution plan, of the plurality of query execution plans that divides the query into a plurality of slave processes for an in-memory scanning operation of at least one of the two tables and a join operation on individual portions the of the two tables; based on a lowest cost estimate of at least the first cost estimate and the second cost estimate, selecting a particular query execution plan among the plurality of query execution plans; maintaining, in a plurality of volatile memories of a plurality of host nodes, a first set of data that belongs to the at least one table; wherein each node of the plurality of host nodes has shared access to a same on-disk version of the first set of data and a second set of data that belongs to another table of the two tables; wherein generating the first cost estimate includes computing the cost of reading, from disk, a partition necessary for joining the two tables that is not located in a given volatile memory of a given host node assigned to perform work against that partition; wherein generating the second cost estimate includes computing the cost of redistributing the first set of data and the second set of data via interprocess communication; wherein the method is performed on one or more computing devices.