diff --git a/cmd/hack/hack.go b/cmd/hack/hack.go
index 59dd11fff63adbe8c359514ab7a86bce51aa86f3..f9786b2a849885e9a40687d303e623bc50dc19b5 100644
--- a/cmd/hack/hack.go
+++ b/cmd/hack/hack.go
@@ -23,6 +23,7 @@ import (
 	"syscall"
 	"time"
 
+	"github.com/AskAlexSharov/lmdb-go/lmdb"
 	"github.com/dustin/go-humanize"
 	"github.com/ledgerwatch/bolt"
 	"github.com/ledgerwatch/turbo-geth/common"
@@ -369,46 +370,52 @@ func accountSavings(db *bolt.DB) (int, int) {
 	return emptyRoots, emptyCodes
 }
 
-func allBuckets(db *bolt.DB) [][]byte {
-	bucketList := [][]byte{}
-	err := db.View(func(tx *bolt.Tx) error {
-		err := tx.ForEach(func(name []byte, b *bolt.Bucket) error {
-			n := make([]byte, len(name))
-			copy(n, name)
-			bucketList = append(bucketList, n)
-			return nil
-		})
-		return err
-	})
-	if err != nil {
-		panic(fmt.Sprintf("Could view db: %s", err))
-	}
-	return bucketList
-}
-
 func printBuckets(db *bolt.DB) {
-	bucketList := allBuckets(db)
-	for _, bucket := range bucketList {
+	for _, bucket := range dbutils.Buckets {
 		fmt.Printf("%s\n", bucket)
 	}
 }
 
 func bucketStats(chaindata string) {
-	db, err := bolt.Open(chaindata, 0600, &bolt.Options{ReadOnly: true})
-	check(err)
-	bucketList := allBuckets(db)
-	//bucketList := [][]byte{dbutils.IntermediateTrieHashBucket}
-	fmt.Printf(",BranchPageN,BranchOverflowN,LeafPageN,LeafOverflowN,KeyN,Depth,BranchAlloc,BranchInuse,LeafAlloc,LeafInuse,BucketN,InlineBucketN,InlineBucketInuse\n")
-	db.View(func(tx *bolt.Tx) error {
-		for _, bucket := range bucketList {
-			b := tx.Bucket(bucket)
-			bs := b.Stats()
-			fmt.Printf("%s,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n", string(bucket),
-				bs.BranchPageN, bs.BranchOverflowN, bs.LeafPageN, bs.LeafOverflowN, bs.KeyN, bs.Depth, bs.BranchAlloc, bs.BranchInuse,
-				bs.LeafAlloc, bs.LeafInuse, bs.BucketN, bs.InlineBucketN, bs.InlineBucketInuse)
-		}
-		return nil
-	})
+	t := ethdb.Bolt
+	bucketList := dbutils.Buckets
+
+	switch t {
+	case ethdb.Bolt:
+		db, err := bolt.Open(chaindata, 0600, &bolt.Options{ReadOnly: true})
+		check(err)
+		//bucketList := [][]byte{dbutils.IntermediateTrieHashBucket}
+
+		fmt.Printf(",BranchPageN,BranchOverflowN,LeafPageN,LeafOverflowN,KeyN,Depth,BranchAlloc,BranchInuse,LeafAlloc,LeafInuse,BucketN,InlineBucketN,InlineBucketInuse\n")
+		_ = db.View(func(tx *bolt.Tx) error {
+			for _, bucket := range bucketList {
+				b := tx.Bucket(bucket)
+				bs := b.Stats()
+				fmt.Printf("%s,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n", string(bucket),
+					bs.BranchPageN, bs.BranchOverflowN, bs.LeafPageN, bs.LeafOverflowN, bs.KeyN, bs.Depth, bs.BranchAlloc, bs.BranchInuse,
+					bs.LeafAlloc, bs.LeafInuse, bs.BucketN, bs.InlineBucketN, bs.InlineBucketInuse)
+			}
+			return nil
+		})
+	case ethdb.Lmdb:
+		env, err := lmdb.NewEnv()
+		check(err)
+		err = env.Open(chaindata, lmdb.Readonly, 0664)
+		check(err)
+
+		fmt.Printf(",BranchPageN,LeafPageN,OverflowN,Entries\n")
+		_ = env.View(func(tx *lmdb.Txn) error {
+			for _, bucket := range bucketList {
+				dbi, bucketErr := tx.OpenDBI(string(bucket), lmdb.Readonly)
+				check(bucketErr)
+				bs, statErr := tx.Stat(dbi)
+				check(statErr)
+				fmt.Printf("%s,%d,%d,%d,%d\n", string(bucket),
+					bs.BranchPages, bs.LeafPages, bs.OverflowPages, bs.Entries)
+			}
+			return nil
+		})
+	}
 }
 
 func readTrieLog() ([]float64, map[int][]float64, []float64) {
diff --git a/ethdb/kv_abstract.go b/ethdb/kv_abstract.go
index a95ededfdedd377d3e448dd45d09a12b670a0baa..426b6319d126ec2807e43436360e04c28303f878 100644
--- a/ethdb/kv_abstract.go
+++ b/ethdb/kv_abstract.go
@@ -26,6 +26,8 @@ type Bucket interface {
 	Put(key []byte, value []byte) error
 	Delete(key []byte) error
 	Cursor() Cursor
+
+	Size() (uint64, error)
 }
 
 type Cursor interface {
@@ -62,4 +64,5 @@ const (
 	Bolt DbProvider = iota
 	Badger
 	Remote
+	Lmdb
 )
diff --git a/ethdb/kv_badger.go b/ethdb/kv_badger.go
index d493c06de0604e3f9b8c70a6fb7a5a8c9fab85dc..20da06a8c6f29b371616b50d2275ab4074941f7e 100644
--- a/ethdb/kv_badger.go
+++ b/ethdb/kv_badger.go
@@ -278,6 +278,10 @@ func (b badgerBucket) Delete(key []byte) error {
 	return b.tx.badger.Delete(b.prefix)
 }
 
+func (b badgerBucket) Size() (uint64, error) {
+	panic("not implemented")
+}
+
 func (b badgerBucket) Cursor() Cursor {
 	c := badgerCursorPool.Get().(*badgerCursor)
 	c.bucket = b
diff --git a/ethdb/kv_bolt.go b/ethdb/kv_bolt.go
index c8ea0daaf096be6a8216844b98d5cef0ba5b1fec..bd7ca0e109046aa405b69ab0028ee64bd5aa483c 100644
--- a/ethdb/kv_bolt.go
+++ b/ethdb/kv_bolt.go
@@ -3,6 +3,7 @@ package ethdb
 import (
 	"bytes"
 	"context"
+	"os"
 	"sync"
 
 	"github.com/ledgerwatch/bolt"
@@ -229,6 +230,11 @@ func (c *boltCursor) NoValues() NoValuesCursor {
 	return &noValuesBoltCursor{boltCursor: c}
 }
 
+func (b boltBucket) Size() (uint64, error) {
+	st := b.bolt.Stats()
+	return uint64((st.BranchPageN + st.BranchOverflowN + st.LeafPageN) * os.Getpagesize()), nil
+}
+
 func (b boltBucket) Get(key []byte) (val []byte, err error) {
 	select {
 	case <-b.tx.ctx.Done():
diff --git a/ethdb/kv_lmdb.go b/ethdb/kv_lmdb.go
index 5501c3d5ccf38a2c8b32ceba9ae9b4590839195a..f91d966fd94d8957aec0514d2d783dd097e22c27 100644
--- a/ethdb/kv_lmdb.go
+++ b/ethdb/kv_lmdb.go
@@ -48,7 +48,6 @@ func (opts lmdbOpts) Open(ctx context.Context) (KV, error) {
 	if err != nil {
 		return nil, err
 	}
-
 	err = env.SetMaxDBs(100)
 	if err != nil {
 		return nil, err
@@ -369,6 +368,14 @@ func (b lmdbBucket) Delete(key []byte) error {
 	return err
 }
 
+func (b lmdbBucket) Size() (uint64, error) {
+	st, err := b.tx.tx.Stat(b.dbi)
+	if err != nil {
+		return 0, err
+	}
+	return (st.LeafPages + st.BranchPages + st.OverflowPages) * uint64(os.Getpagesize()), nil
+}
+
 func (b lmdbBucket) Cursor() Cursor {
 	c := lmdbKvCursorPool.Get().(*lmdbCursor)
 	c.ctx = b.tx.ctx
diff --git a/ethdb/kv_remote.go b/ethdb/kv_remote.go
index 4c65dcc257ba923e30db7116f4cd4aa821063598..11292a7c765f805fad210b9aafb5fe229c107d28 100644
--- a/ethdb/kv_remote.go
+++ b/ethdb/kv_remote.go
@@ -180,6 +180,10 @@ func (c *remoteCursor) NoValues() NoValuesCursor {
 	return &remoteNoValuesCursor{remoteCursor: c}
 }
 
+func (b remoteBucket) Size() (uint64, error) {
+	panic("not implemented")
+}
+
 func (b remoteBucket) Get(key []byte) (val []byte, err error) {
 	val, err = b.remote.Get(key)
 	return val, err