@Override
  public long computeIndexLookupCosts(
      IndexDescriptor index, TableDescriptor baseTable, long cardinality) {

    PageSize indexPageSize = index.getSchema().getPageSize();
    PageSize tablePageSize = baseTable.getSchema().getPageSize();

    long BTreeCost =
        (index.getStatistics().getTreeDepth() - 2)
            * (getReadCost(indexPageSize) + randomReadOverhead);

    long pageNbr;

    if (cardinality == baseTable.getStatistics().getCardinality())
      pageNbr = index.getStatistics().getNumberOfLeafs() + 1;
    else
      pageNbr =
          (long)
              Math.ceil(
                  index.getStatistics().getNumberOfLeafs()
                      * 1.0f
                      * cardinality
                      / baseTable.getStatistics().getCardinality());

    long scanCost = randomReadOverhead + pageNbr * getReadCost(tablePageSize);

    return BTreeCost + scanCost;
  }
  @Override
  public long computeTableScanCosts(TableDescriptor table) {

    PageSize pageSize = table.getSchema().getPageSize();

    int pageNbr = table.getStatistics().getNumberOfPages();

    return randomReadOverhead + pageNbr * getReadCost(pageSize);
  }
  @Override
  public long computeFetchCosts(
      TableDescriptor fetchedTable, long cardinality, boolean sequential) {

    PageSize pageSize = fetchedTable.getSchema().getPageSize();
    int totalPages = fetchedTable.getStatistics().getNumberOfPages();

    if (sequential) {

      float k = 1.0f * (totalPages - 1) / totalPages;

      //	double nbrPages =  (1/k - 1/(k- Math.pow(k, 2))) * Math.pow(k, cardinality)+ 1/(1-k);

      double nbrPages = Math.floor((1 - Math.pow(k, cardinality)) / (1 - k));
      // nbrPages = 249.05f;

      double ratio = 1 - (1.0f * nbrPages / totalPages) * (7.0f / 8.0f);

      /*System.out.println("k : " + k);
      	System.out.println("total pages : " + totalPages);
      	System.out.println("pages : " + nbrPages);
      	System.out.println("ratio : " + ratio);
      	System.out.println("PageSize : " + pageSize.toString());
      */

      return (long) Math.floor(nbrPages * (getReadCost(pageSize) + ratio * randomReadOverhead));

    } else {

      double B = Math.pow(10 * totalPages, 1.0 / 0.66);
      double H = Math.min(Math.log(cardinality) / Math.log(B), 0.8);

      return (long)
          Math.floor(cardinality * (1 - H) * (getReadCost(pageSize) + randomReadOverhead));
    }
  }