diff --git a/lib/storage/index_db.go b/lib/storage/index_db.go
index 8407d2dfb..4dc275a0e 100644
--- a/lib/storage/index_db.go
+++ b/lib/storage/index_db.go
@@ -1230,20 +1230,35 @@ func (is *indexSearch) getTSIDByMetricID(dst *TSID, metricID uint64, accountID,
 func (is *indexSearch) getSeriesCount(accountID, projectID uint32) (uint64, error) {
 	ts := &is.ts
 	kb := &is.kb
-	var n uint64
-	kb.B = marshalCommonPrefix(kb.B[:0], nsPrefixMetricIDToTSID, accountID, projectID)
+	mp := &is.mp
+	var metricIDsLen uint64
+	// Extract the number of series from ((__name__=value): metricIDs) rows
+	kb.B = marshalCommonPrefix(kb.B[:0], nsPrefixTagToMetricIDs, accountID, projectID)
+	kb.B = marshalTagValue(kb.B, nil)
 	ts.Seek(kb.B)
 	for ts.NextItem() {
-		if !bytes.HasPrefix(ts.Item, kb.B) {
+		item := ts.Item
+		if !bytes.HasPrefix(item, kb.B) {
 			break
 		}
+		tail := item[len(kb.B):]
+		n := bytes.IndexByte(tail, tagSeparatorChar)
+		if n < 0 {
+			return 0, fmt.Errorf("invalid tag->metricIDs line %q: cannot find tagSeparatorChar %d", item, tagSeparatorChar)
+		}
+		tail = tail[n+1:]
+		if err := mp.InitOnlyTail(item, tail); err != nil {
+			return 0, err
+		}
 		// Take into account deleted timeseries too.
-		n++
+		// It is OK if series can be counted multiple times in rare cases -
+		// the returned number is an estimation.
+		metricIDsLen += uint64(mp.MetricIDsLen())
 	}
 	if err := ts.Error(); err != nil {
 		return 0, fmt.Errorf("error when counting unique timeseries: %s", err)
 	}
-	return n, nil
+	return metricIDsLen, nil
 }
 
 // updateMetricIDsByMetricNameMatch matches metricName values for the given srcMetricIDs against tfs
@@ -2126,7 +2141,11 @@ func (is *indexSearch) containsTimeRange(tr TimeRange, accountID, projectID uint
 func (is *indexSearch) updateMetricIDsAll(metricIDs *uint64set.Set, accountID, projectID uint32, maxMetrics int) error {
 	ts := &is.ts
 	kb := &is.kb
-	kb.B = marshalCommonPrefix(kb.B[:0], nsPrefixMetricIDToTSID, accountID, projectID)
+	mp := &is.mp
+
+	// Extract all the mtricIDs from (__name__=value) metricIDs.
+	kb.B = marshalCommonPrefix(kb.B[:0], nsPrefixTagToMetricIDs, accountID, projectID)
+	kb.B = marshalTagValue(kb.B, nil)
 	prefix := kb.B
 	ts.Seek(prefix)
 	for ts.NextItem() {
@@ -2135,11 +2154,18 @@ func (is *indexSearch) updateMetricIDsAll(metricIDs *uint64set.Set, accountID, p
 			return nil
 		}
 		tail := item[len(prefix):]
-		if len(tail) < 8 {
-			return fmt.Errorf("cannot unmarshal metricID from item with size %d; need at least 9 bytes; item=%q", len(tail), tail)
+		n := bytes.IndexByte(tail, tagSeparatorChar)
+		if n < 0 {
+			return fmt.Errorf("invalid tag->metricIDs line %q: cannot find tagSeparatorChar %d", item, tagSeparatorChar)
+		}
+		tail = tail[n+1:]
+		if err := mp.InitOnlyTail(item, tail); err != nil {
+			return err
+		}
+		mp.ParseMetricIDs()
+		for _, metricID := range mp.MetricIDs {
+			metricIDs.Add(metricID)
 		}
-		metricID := encoding.UnmarshalUint64(tail)
-		metricIDs.Add(metricID)
 		if metricIDs.Len() >= maxMetrics {
 			return nil
 		}