如何使用java驱动程序执行mongodb getShardDistribution()

时间:2014-07-22 11:46:04

标签: java mongodb mongodb-query

我有以下mongoDB命令来了解分片中的数据分布:

db.images.getShardDistribution()

如何使用java执行此mongoDB shard命令?

1 个答案:

答案 0 :(得分:0)

以下是我在Java中的实现:

Requierements:
 - org.mongodb:mongo-java-driver:2.12.5 >=
 - log4j:log4j:1.2.17 >=

/**
     * Prints the data distribution statistics for a sharded collection. 
     * You must call the getShardDistribution() method on a sharded collection, 
     * as in the following example:
     * db.myShardedCollection.getShardDistribution()
     * @param collection sharded collection
     */
    public static void getShardDistribution(DBCollection collection){

        CommandResult stats = collection.getStats();

        // Check if collection is sharded
        if(stats.get("sharded") != null && (Boolean) stats.get("sharded")){

            DB config = collection.getDB().getSisterDB("config");
            Integer numChunks = 0;
            BasicDBObject shards = (BasicDBObject) stats.get("shards");

            for(String key: shards.keySet()){

                DBObject shardDoc = config.getCollection("shards").findOne(new BasicDBObject("_id", key));
                LOG.info("Shard " + key + " at " + ((shardDoc != null) ? shardDoc.get("host") : " shardDoc not found"));

                DBObject shardStats = (DBObject) shards.get(key);
                Pattern chunkPattern = Pattern.compile("^" + collection.getDB().getName() + "." + collection.getName() + "-.*", Pattern.CASE_INSENSITIVE);

                List<DBObject> chunks = config.getCollection("chunks")
                                              .find(new BasicDBObject()
                                                        .append("_id", chunkPattern)
                                                        .append("shard", key)
                                              ).toArray();
                numChunks += chunks.size();

                int    estChunkData  = (int)shardStats.get("size") / chunks.size();
                Double estChunkCount = Math.floor((int)shardStats.get("count") / chunks.size());

                LOG.info(" data : " + humanReadableByteCount((int)shardStats.get("size")) + " docs : " + shardStats.get("count") + " chunks : " + chunks.size());
                LOG.info(" estimated data per chunk : " + humanReadableByteCount(estChunkData));
                LOG.info(" estimated docs per chunk : " + estChunkCount.intValue());
            }

            LOG.info("");
            LOG.info("Totals");
            LOG.info(" data : " + humanReadableByteCount((int)stats.get("size")) + " docs : " + stats.get("count") + " chunks : " + numChunks);

            for(String key: shards.keySet()){

                DBObject shardStats = (DBObject) shards.get(key);

                // Check if avgObjSize is empty
                if(!shardStats.containsField("avgObjSize")){
                    shardStats.put("avgObjSize", 0);
                }
                double estDataPercent = ((int)shardStats.get("size") / ((int)stats.get("size") * 1.)) * 100;
                double estDocPercent  = ((int)shardStats.get("count") / ((int)stats.get("count") * 1.)) * 100;
                LOG.info(String.format(Locale.ENGLISH, " Shard %s contains %.1f%% data, %.1f%% docs in cluster, avg obj size on shard : %s", 
                            key, 
                            estDataPercent, 
                            estDocPercent, 
                            humanReadableByteCount((int)shardStats.get("avgObjSize")))
                        );
            }

        }else{
            LOG.warn("Collection " + collection.getName() + " is not sharded.");
            LOG.warn("More info: " + stats);
        }
    }

    /**
     * Returns human readable byte count with handles both SI units and binary units
     * @param bytes total bytes
     * @return Formatted string of byte measure
     */
    public static String humanReadableByteCount(long bytes) {
        int unit = 1024;
        if (bytes < unit) return bytes + " b";
        int exp = (int) (Math.log(bytes) / Math.log(unit));
        String pre = ("kMGTPE").charAt(exp-1) + "";
        return String.format(Locale.ENGLISH, "%.2f %sb", bytes / Math.pow(unit, exp), pre);
    }