Package edu.brown.statistics

Source Code of edu.brown.statistics.TableStatistics

/***************************************************************************
*   Copyright (C) 2009 by H-Store Project                                 *
*   Brown University                                                      *
*   Massachusetts Institute of Technology                                 *
*   Yale University                                                       *
*                                                                         *
*   Permission is hereby granted, free of charge, to any person obtaining *
*   a copy of this software and associated documentation files (the       *
*   "Software"), to deal in the Software without restriction, including   *
*   without limitation the rights to use, copy, modify, merge, publish,   *
*   distribute, sublicense, and/or sell copies of the Software, and to    *
*   permit persons to whom the Software is furnished to do so, subject to *
*   the following conditions:                                             *
*                                                                         *
*   The above copyright notice and this permission notice shall be        *
*   included in all copies or substantial portions of the Software.       *
*                                                                         *
*   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       *
*   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    *
*   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*
*   IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR     *
*   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
*   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
*   OTHER DEALINGS IN THE SOFTWARE.                                       *
***************************************************************************/
package edu.brown.statistics;

import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;

import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONStringer;
import org.voltdb.VoltTableRow;
import org.voltdb.VoltType;
import org.voltdb.catalog.Column;
import org.voltdb.catalog.Database;
import org.voltdb.catalog.Statement;
import org.voltdb.catalog.Table;
import org.voltdb.types.QueryType;

import edu.brown.catalog.CatalogKey;
import edu.brown.catalog.CatalogUtil;
import edu.brown.designer.MemoryEstimator;
import edu.brown.workload.QueryTrace;
import edu.brown.workload.TransactionTrace;

/**
* @author pavlo
*/
public class TableStatistics extends AbstractStatistics<Table> {

    public enum Members {
        // Whether this table was read-only in the workload
        READONLY,

        // Estimate number of tuples (based on the number of inserts)
        TUPLE_COUNT_TOTAL,

        // Estimate tuple sizes
        TUPLE_SIZE_TOTAL, TUPLE_SIZE_MIN, TUPLE_SIZE_MAX, TUPLE_SIZE_AVG,

        // The type of queries used on this table
        QUERY_TYPE_COUNT,

        // Column statistics
        COLUMN_STATS,
    };

    /** Total number of tuples in the table */
    public Long tuple_count_total = 0l;
    /** Total number of bytes for the table */
    public Long tuple_size_total = 0l;
    /** The minimum size of a tupe in the table */
    public Long tuple_size_min = null;
    /** The maximum size of a tuple in the table */
    public Long tuple_size_max = null;
    /** The average size of a tuple in the table */
    public Long tuple_size_avg = 0l;
    /** Is this table readonly */
    public Boolean readonly = true;

    public final SortedMap<QueryType, Long> query_type_count = new TreeMap<QueryType, Long>();
    public final SortedMap<String, ColumnStatistics> column_stats = new TreeMap<String, ColumnStatistics>();

    /**
     * Options
     */
    protected boolean estimateSize = true;
    protected boolean estimateCount = false;

    //
    // The field types we will record
    //
    public static final Set<VoltType> TARGET_COLUMN_TYPES = new HashSet<VoltType>();
    static {
        TARGET_COLUMN_TYPES.add(VoltType.TINYINT);
        TARGET_COLUMN_TYPES.add(VoltType.INTEGER);
        TARGET_COLUMN_TYPES.add(VoltType.BIGINT);
    };

    private final transient Set<ColumnStatistics> target_columns = new HashSet<ColumnStatistics>();

    /**
     * Construtor
     *
     * @param catalog_key
     */
    public TableStatistics(String catalog_key) {
        super(catalog_key);
    }

    public TableStatistics(Table catalog_tbl) {
        super(catalog_tbl);
        this.preprocess((Database) catalog_tbl.getParent());
    }

    @Override
    public Table getCatalogItem(Database catalog_db) {
        Table ret = CatalogKey.getFromKey(catalog_db, this.catalog_key, Table.class);
        if (ret == null) {
            System.err.println("catalog_key: " + this.catalog_key);
            System.err.println("tables:      " + CatalogUtil.debug(catalog_db.getTables()));
        }
        return (ret);
    }

    public Collection<ColumnStatistics> getColumnStatistics() {
        return (this.column_stats.values());
    }

    public ColumnStatistics getColumnStatistics(Column catalog_col) {
        String col_key = CatalogKey.createKey(catalog_col);
        return (this.getColumnStatistics(col_key));
    }

    public ColumnStatistics getColumnStatistics(String col_key) {
        return (this.column_stats.get(col_key));
    }

    public void process(Database catalog_db, VoltTableRow row) {
        long rowSize = row.getRowSize();
        this.tuple_count_total++;
        this.tuple_size_total += rowSize;

        if (this.tuple_size_min == null || this.tuple_size_min > rowSize) {
            this.tuple_size_min = rowSize;
        }
        if (this.tuple_size_max == null || this.tuple_size_max > rowSize) {
            this.tuple_size_max = rowSize;
        }

        // XXX: Should we call call process for the ColumnStats?
    }

    @Override
    public void preprocess(Database catalog_db) {
        if (this.has_preprocessed)
            return;

        Table catalog_tbl = this.getCatalogItem(catalog_db);

        for (QueryType type : QueryType.values()) {
            this.query_type_count.put(type, 0l);
        } // FOR
        for (Column catalog_col : catalog_tbl.getColumns()) {
            String col_key = CatalogKey.createKey(catalog_col);
            this.column_stats.put(col_key, new ColumnStatistics(catalog_col));
        } // FOR

        this.has_preprocessed = true;
    }

    @Override
    public void process(Database catalog_db, TransactionTrace xact) throws Exception {
        final Table catalog_tbl = this.getCatalogItem(catalog_db);
        // For each query, check whether they are going to our table
        // If so, then we need to update our statistics
        for (QueryTrace query : xact.getQueries()) {
            Statement catalog_stmt = query.getCatalogItem(catalog_db);
            QueryType query_type = QueryType.get(catalog_stmt.getQuerytype());
            // System.out.println("Examining " + catalog_stmt + " for " +
            // catalog_tbl);

            if (CatalogUtil.getReferencedTables(catalog_stmt).contains(catalog_tbl)) {
                // Query Type Counts
                this.query_type_count.put(query_type, this.query_type_count.get(query_type) + 1);

                // Read-only
                if (query_type == QueryType.INSERT || query_type == QueryType.UPDATE || query_type == QueryType.DELETE) {
                    this.readonly = false;
                }

                // Now from this point forward we only want to look at INSERTs
                // because
                // that's the only way we can estimate tuple sizes
                if (query_type == QueryType.INSERT) {
                    this.tuple_count_total += 1;
                    Long bytes = 0l;
                    try {
                        bytes = (long) MemoryEstimator.estimateTupleSize(catalog_tbl, catalog_stmt, query.getParams()).intValue();
                    } catch (ArrayIndexOutOfBoundsException ex) {
                        // Silently let these pass...
                        LOG.debug("Failed to calculate estimated tuple size for " + query, ex);
                    }
                    this.tuple_size_total += bytes;
                    if (bytes != 0 && (this.tuple_size_min == null || this.tuple_size_min > bytes)) {
                        this.tuple_size_min = bytes;
                    }
                    if (this.tuple_size_max == null || this.tuple_size_max < bytes) {
                        this.tuple_size_max = bytes;
                    }
                }

                // Column Stats
                if (query_type == QueryType.INSERT) {
                    if (this.target_columns.isEmpty()) {
                        for (Column catalog_col : catalog_tbl.getColumns()) {
                            VoltType col_type = VoltType.get((byte) catalog_col.getType());
                            if (TARGET_COLUMN_TYPES.contains(col_type)) {
                                String col_key = CatalogKey.createKey(catalog_col);
                                this.target_columns.add(this.column_stats.get(col_key));
                            }
                        } // FOR
                    }
                    for (ColumnStatistics col_stats : this.target_columns) {
                        col_stats.process(catalog_db, xact);
                    } // FOR
                }
            } // IF
        } // FOR
        return;
    }

    @Override
    public void postprocess(Database catalog_db) throws Exception {
        if (this.tuple_count_total > 0) {
            this.tuple_size_avg = this.tuple_size_total / this.tuple_count_total;
        }
    }

    @Override
    public String debug(Database catalog_db) {
        return (this.debug(catalog_db, TableStatistics.Members.values()));
    }

    @Override
    public void toJSONString(JSONStringer stringer) throws JSONException {
        // Tuple Counts
        stringer.key(Members.TUPLE_COUNT_TOTAL.name()).value(this.tuple_count_total);

        // Tuple Sizes
        stringer.key(Members.TUPLE_SIZE_TOTAL.name()).value(this.tuple_size_total);
        stringer.key(Members.TUPLE_SIZE_MIN.name()).value(this.tuple_size_min);
        stringer.key(Members.TUPLE_SIZE_MAX.name()).value(this.tuple_size_max);
        stringer.key(Members.TUPLE_SIZE_AVG.name()).value(this.tuple_size_avg);

        // Read-only
        stringer.key(Members.READONLY.name()).value(this.readonly);

        // Query Type Counts
        this.writeMap(this.query_type_count, Members.QUERY_TYPE_COUNT.name(), stringer);

        // Column Stats
        stringer.key(Members.COLUMN_STATS.name()).object();
        for (String col_key : this.column_stats.keySet()) {
            stringer.key(col_key).object();
            this.column_stats.get(col_key).toJSONString(stringer);
            stringer.endObject();
        } // FOR
        stringer.endObject();
    }

    @Override
    public void fromJSONObject(JSONObject object, Database catalog_db) throws JSONException {
        this.preprocess(catalog_db);

        // Tuple Counts
        this.tuple_count_total = object.getLong(Members.TUPLE_COUNT_TOTAL.name());

        // Tuple Sizes
        this.tuple_size_total = object.getLong(Members.TUPLE_SIZE_TOTAL.name());

        if (!object.isNull(Members.TUPLE_SIZE_MIN.name())) {
            this.tuple_size_min = object.getLong(Members.TUPLE_SIZE_MIN.name());
        }
        if (!object.isNull(Members.TUPLE_SIZE_MAX.name())) {
            this.tuple_size_max = object.getLong(Members.TUPLE_SIZE_MAX.name());
        }
        this.tuple_size_avg = object.getLong(Members.TUPLE_SIZE_AVG.name());

        // Read-only
        this.readonly = object.getBoolean(Members.READONLY.name());

        // Query Type Counts
        this.readMap(this.query_type_count, Members.QUERY_TYPE_COUNT.name(), QueryType.getNameMap(), Long.class, object);

        // Column Stats
        if (object.has(Members.COLUMN_STATS.name())) {
            JSONObject jsonObject = object.getJSONObject(Members.COLUMN_STATS.name());
            Iterator<String> col_keys = jsonObject.keys();
            while (col_keys.hasNext()) {
                String col_key = col_keys.next();
                Column catalog_col = CatalogKey.getFromKey(catalog_db, col_key, Column.class);
                ColumnStatistics col_stats = new ColumnStatistics(catalog_col);
                col_stats.fromJSONObject(jsonObject.getJSONObject(col_key), catalog_db);
                this.column_stats.put(col_key, col_stats);
            } // WHILE
        }
    }
}
TOP

Related Classes of edu.brown.statistics.TableStatistics

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.