diff --git a/pkg/local_object_storage/metabase/bucket_cache.go b/pkg/local_object_storage/metabase/bucket_cache.go
new file mode 100644
index 000000000..b425450af
--- /dev/null
+++ b/pkg/local_object_storage/metabase/bucket_cache.go
@@ -0,0 +1,45 @@
+package meta
+
+import (
+	"go.etcd.io/bbolt"
+)
+
+type bucketCache struct {
+	locked    *bbolt.Bucket
+	graveyard *bbolt.Bucket
+	garbage   *bbolt.Bucket
+}
+
+func newBucketCache() *bucketCache {
+	return &bucketCache{}
+}
+
+func getLockedBucket(bc *bucketCache, tx *bbolt.Tx) *bbolt.Bucket {
+	if bc == nil {
+		return tx.Bucket(bucketNameLocked)
+	}
+	return getBucket(&bc.locked, tx, bucketNameLocked)
+}
+
+func getGraveyardBucket(bc *bucketCache, tx *bbolt.Tx) *bbolt.Bucket {
+	if bc == nil {
+		return tx.Bucket(graveyardBucketName)
+	}
+	return getBucket(&bc.graveyard, tx, graveyardBucketName)
+}
+
+func getGarbageBucket(bc *bucketCache, tx *bbolt.Tx) *bbolt.Bucket {
+	if bc == nil {
+		return tx.Bucket(garbageBucketName)
+	}
+	return getBucket(&bc.garbage, tx, garbageBucketName)
+}
+
+func getBucket(cache **bbolt.Bucket, tx *bbolt.Tx, name []byte) *bbolt.Bucket {
+	if *cache != nil {
+		return *cache
+	}
+
+	*cache = tx.Bucket(name)
+	return *cache
+}
diff --git a/pkg/local_object_storage/metabase/exists.go b/pkg/local_object_storage/metabase/exists.go
index 962108a76..0b28da5c9 100644
--- a/pkg/local_object_storage/metabase/exists.go
+++ b/pkg/local_object_storage/metabase/exists.go
@@ -153,8 +153,12 @@ func (db *DB) exists(tx *bbolt.Tx, addr oid.Address, ecParent oid.Address, currE
 //   - 2 if object is covered with tombstone;
 //   - 3 if object is expired.
 func objectStatus(tx *bbolt.Tx, addr oid.Address, currEpoch uint64) (uint8, error) {
+	return objectStatusWithCache(nil, tx, addr, currEpoch)
+}
+
+func objectStatusWithCache(bc *bucketCache, tx *bbolt.Tx, addr oid.Address, currEpoch uint64) (uint8, error) {
 	// locked object could not be removed/marked with GC/expired
-	if objectLocked(tx, addr.Container(), addr.Object()) {
+	if objectLockedWithCache(bc, tx, addr.Container(), addr.Object()) {
 		return 0, nil
 	}
 
@@ -167,8 +171,8 @@ func objectStatus(tx *bbolt.Tx, addr oid.Address, currEpoch uint64) (uint8, erro
 		return 3, nil
 	}
 
-	graveyardBkt := tx.Bucket(graveyardBucketName)
-	garbageBkt := tx.Bucket(garbageBucketName)
+	graveyardBkt := getGraveyardBucket(bc, tx)
+	garbageBkt := getGarbageBucket(bc, tx)
 	addrKey := addressKey(addr, make([]byte, addressKeySize))
 	return inGraveyardWithKey(addrKey, graveyardBkt, garbageBkt), nil
 }
diff --git a/pkg/local_object_storage/metabase/lock.go b/pkg/local_object_storage/metabase/lock.go
index aa1478423..f73c2b4f6 100644
--- a/pkg/local_object_storage/metabase/lock.go
+++ b/pkg/local_object_storage/metabase/lock.go
@@ -163,7 +163,11 @@ func (db *DB) FreeLockedBy(lockers []oid.Address) ([]oid.Address, error) {
 
 // checks if specified object is locked in the specified container.
 func objectLocked(tx *bbolt.Tx, idCnr cid.ID, idObj oid.ID) bool {
-	bucketLocked := tx.Bucket(bucketNameLocked)
+	return objectLockedWithCache(nil, tx, idCnr, idObj)
+}
+
+func objectLockedWithCache(bc *bucketCache, tx *bbolt.Tx, idCnr cid.ID, idObj oid.ID) bool {
+	bucketLocked := getLockedBucket(bc, tx)
 	if bucketLocked != nil {
 		key := make([]byte, cidSize)
 		idCnr.Encode(key)
diff --git a/pkg/local_object_storage/metabase/select.go b/pkg/local_object_storage/metabase/select.go
index 4a3b22b55..a95384753 100644
--- a/pkg/local_object_storage/metabase/select.go
+++ b/pkg/local_object_storage/metabase/select.go
@@ -131,6 +131,7 @@ func (db *DB) selectObjects(tx *bbolt.Tx, cnr cid.ID, fs objectSDK.SearchFilters
 
 	res := make([]oid.Address, 0, len(mAddr))
 
+	bc := newBucketCache()
 	for a, ind := range mAddr {
 		if ind != expLen {
 			continue // ignore objects with unmatched fast filters
@@ -145,7 +146,7 @@ func (db *DB) selectObjects(tx *bbolt.Tx, cnr cid.ID, fs objectSDK.SearchFilters
 		var addr oid.Address
 		addr.SetContainer(cnr)
 		addr.SetObject(id)
-		st, err := objectStatus(tx, addr, currEpoch)
+		st, err := objectStatusWithCache(bc, tx, addr, currEpoch)
 		if err != nil {
 			return nil, err
 		}