diff --git a/core/qa/checker/CbmQaCheckerFileHandler.cxx b/core/qa/checker/CbmQaCheckerFileHandler.cxx
index 5f935242ccad50baee55b405b2710c77edcd4905..dd799211d56a2395b822b713981acd23cd7c7908 100644
--- a/core/qa/checker/CbmQaCheckerFileHandler.cxx
+++ b/core/qa/checker/CbmQaCheckerFileHandler.cxx
@@ -115,7 +115,7 @@ void FileHandler::Process(Option_t* opt)
 
     // Create an instance of an object handler
     std::unique_ptr<ObjectHandler> pObjHandler = nullptr;
-    LOG(info) << "FileHandler: processing object \"" << vpObjects[0]->GetName() << '\"';
+    //LOG(info) << "FileHandler: processing object \"" << vpObjects[0]->GetName() << '\"';
     if (dynamic_cast<TH2*>(vpObjects[0])) {
       pObjHandler = std::make_unique<Hist2DHandler>(iObj, fFileID, fDatasetID);
       if (bCmpPointByPoint) {
diff --git a/core/qa/checker/CbmQaCheckerObjectDB.cxx b/core/qa/checker/CbmQaCheckerObjectDB.cxx
index abf083a8c3b1c944f608ce175030ccf316dfd57a..44f4ed3d9dce445863b693d0be135350e2146232 100644
--- a/core/qa/checker/CbmQaCheckerObjectDB.cxx
+++ b/core/qa/checker/CbmQaCheckerObjectDB.cxx
@@ -1,4 +1,4 @@
-/* Copyright (C) 2023 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
+/* Copyright (C) 2023-2024 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
    SPDX-License-Identifier: GPL-3.0-only
    Authors: Sergei Zharko [committer] */
 
@@ -10,6 +10,10 @@
 #include "CbmQaCheckerObjectDB.h"
 
 #include "Logger.h"
+#include "TDirectory.h"
+#include "TFile.h"
+#include "TH1.h"
+#include "TString.h"
 
 #include <algorithm>
 #include <regex>
@@ -29,24 +33,10 @@ void ObjectDB::Clear()
   fvObjects.clear();
   fvVersionLabels.clear();
   fvVersionPaths.clear();
-  fvGlobalToFileObject.clear();
+  fvObjectFirstGlobIndex.clear();
   fvCmpResults.clear();
 }
 
-// ---------------------------------------------------------------------------------------------------------------------
-//
-// ObjectDB::GetObjects(int iFile) const
-// {
-//   auto itBegin = std::upper_bound(fvGlobalToFileObject.begin(), fvGlobalToFileObject.end(), iFile,
-//     [](int i, const std::pair<int, int>& p) { return i <= p.first; });
-//   auto itEnd   = std::lower_bound(itBegin, fvGlobalToFileObject.end(), iFile,
-//     [](const std::pair<int, int>& p, int i) { return i >= p.first; });
-//
-//   int iBegin = itBegin - fvGlobalToFileObject.begin();
-//   int iEnd   = itEnd - fvGlobalToFileObject.begin();
-//   return boost::make_iterator_range(fvObjects.begin() + iBegin, fvObjects.begin() + iEnd);
-// }
-
 // ---------------------------------------------------------------------------------------------------------------------
 //
 void ObjectDB::AddVersion(const char* label, const char* path)
@@ -69,6 +59,7 @@ std::string ObjectDB::GetInputFileName(int iVersion, int iFile, int iDataset) co
   return res;
 }
 
+
 // ---------------------------------------------------------------------------------------------------------------------
 //
 void ObjectDB::Init()
@@ -100,8 +91,22 @@ void ObjectDB::Init()
   }
   LOG(info) << this->ToString();
 
+  // ----- Read object list from file
+  for (size_t iFile = 0; iFile < fvObjects.size(); ++iFile) {
+    if (fvObjects[iFile].size() == 0) {
+      this->ReadObjectList(iFile);
+    }
+  }
+
+  // ----- Init the object index vector
+  fvObjectFirstGlobIndex.clear();
+  fvObjectFirstGlobIndex.resize(fvObjects.size() + 1, 0);
+  for (size_t iFile = 1; iFile <= fvObjects.size(); ++iFile) {
+    fvObjectFirstGlobIndex[iFile] = fvObjectFirstGlobIndex[iFile - 1] + fvObjects[iFile - 1].size();
+  }
+
   // ----- Reserve space for object comparison results
-  fvCmpResults.resize(fvVersionLabels.size() * fvObjects.size() * fvDatasets.size());
+  fvCmpResults.resize(fvVersionLabels.size() * fvObjectFirstGlobIndex.back() * fvDatasets.size());
 
   // ----- Add root path of input, if it were defined
   auto regexSlashes = std::regex("(/+)");  // regular expression for a sequence of consecutive slashes
@@ -131,9 +136,8 @@ void ObjectDB::ReadFromYAML(const char* configName)
 
   // ----- Define file-object map
   if (config["files"]) {
-    if (fvGlobalToFileObject.size()) {
+    if (fvObjectFirstGlobIndex.size()) {
       LOG(warn) << "ObjectDB: file-object map was defined before. Redefining it from the config file " << configName;
-      fvGlobalToFileObject.clear();
       fvFiles.clear();
       fvFileLabels.clear();
       fvObjects.clear();
@@ -142,22 +146,21 @@ void ObjectDB::ReadFromYAML(const char* configName)
       const auto& rootNode = config["files"];
 
       // Calculate total number of objects and files
-      size_t nFiles   = rootNode.size();
-      size_t nObjects = 0;
-      for (const auto& fileNode : rootNode) {
-        nObjects += fileNode["objects"].size();
-      }
+      size_t nFiles = rootNode.size();
       fvFiles.reserve(nFiles);
       fvFileLabels.reserve(nFiles);
-      fvObjects.reserve(nObjects);
-      fvGlobalToFileObject.reserve(nObjects);
+      fvObjects.reserve(nFiles);
 
       // Fill vectors
       for (const auto& fileNode : rootNode) {
-        size_t iObj = 0;
-        for (const auto& objectNode : fileNode["objects"]) {
-          fvGlobalToFileObject.emplace_back(fvFiles.size(), iObj++);
-          fvObjects.push_back(objectNode.as<std::string>());
+        const auto& objectsNode = fileNode["objects"];
+        int nObjects            = objectsNode ? objectsNode.size() : 0;
+        auto& objectsInFile     = fvObjects.emplace_back();
+        objectsInFile.reserve(nObjects);
+        if (nObjects > 0) {
+          for (const auto& objectNode : objectsNode) {
+            objectsInFile.push_back(objectNode.as<std::string>());
+          }
         }
         fvFiles.push_back(fileNode["name"].as<std::string>());
         fvFileLabels.push_back(fileNode["label"].as<std::string>());
@@ -223,6 +226,42 @@ void ObjectDB::ReadFromYAML(const char* configName)
   }
 }
 
+// ---------------------------------------------------------------------------------------------------------------------
+//
+void ObjectDB::CollectObjectPaths(TDirectory* pDir, const TString& parentPath, std::set<std::string>& paths)
+{
+  for (auto&& pKey : *(pDir->GetListOfKeys())) {
+    TString sName = parentPath + pKey->GetName();
+    if (gFile->Get<TH1>(sName)) {
+      paths.insert(sName.Data());
+    }
+    else if (auto* pSubDir = gFile->Get<TDirectory>(sName)) {
+      CollectObjectPaths(pSubDir, sName + "/", paths);
+    }
+  }
+}
+
+// ---------------------------------------------------------------------------------------------------------------------
+//
+void ObjectDB::ReadObjectList(int iFile)
+{
+  // TODO: test performance, probably unordered_set will fit better
+  std::set<std::string> objectPaths;
+  LOG(info) << "Reading object list from files: ...";
+  for (int iDs = 0; iDs < static_cast<int>(fvDatasets.size()); ++iDs) {
+    const char* fileName = this->GetInputFileName(fDefVersionID, iFile, iDs).c_str();
+    LOG(info) << "- file: " << fileName;
+    TFile fileIn{fileName, "READONLY"};
+    fileIn.cd();
+    CollectObjectPaths(&fileIn, "", objectPaths);
+    fileIn.Close();
+  }
+  fvObjects[iFile].clear();
+  fvObjects[iFile].reserve(objectPaths.size());
+  fvObjects[iFile].insert(fvObjects[iFile].begin(), objectPaths.begin(), objectPaths.end());
+  LOG(info) << "Reading object list from files: done";
+}
+
 // ---------------------------------------------------------------------------------------------------------------------
 //
 std::string ObjectDB::ToString() const
diff --git a/core/qa/checker/CbmQaCheckerObjectDB.h b/core/qa/checker/CbmQaCheckerObjectDB.h
index 7a0eccabc0fcd11ca72542774eca3bafeb7db721..dc73e1e4fdfea5400886bdd95f406d7dc9d37e2c 100644
--- a/core/qa/checker/CbmQaCheckerObjectDB.h
+++ b/core/qa/checker/CbmQaCheckerObjectDB.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2023 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
+/* Copyright (C) 2023-2024 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
    SPDX-License-Identifier: GPL-3.0-only
    Authors: Sergei Zharko [committer] */
 
@@ -12,10 +12,13 @@
 
 #include "CbmQaCheckerTypedefs.h"
 
+#include <set>
 #include <string>
 #include <utility>
 #include <vector>
 
+class TString;
+class TDirectory;
 
 namespace cbm::qa::checker
 {
@@ -74,18 +77,7 @@ namespace cbm::qa::checker
     /// @param iFile  Index of file
     /// @return  iterator_range for ROOT objects of this file
     /// TODO: Understand, which type is deduced
-    auto GetObjects(int iFile) const
-    {
-      auto itBegin = std::upper_bound(fvGlobalToFileObject.begin(), fvGlobalToFileObject.end(), iFile,
-                                      [](int i, const std::pair<int, int>& p) { return i <= p.first; });
-      auto itEnd   = std::lower_bound(itBegin, fvGlobalToFileObject.end(), iFile,
-                                    [](const std::pair<int, int>& p, int i) { return i >= p.first; });
-
-      int iBegin = itBegin - fvGlobalToFileObject.begin();
-      int iEnd   = itEnd - fvGlobalToFileObject.begin();
-
-      return boost::make_iterator_range(fvObjects.begin() + iBegin, fvObjects.begin() + iEnd);
-    }
+    const std::vector<std::string>& GetObjects(int iFile) const { return fvObjects[iFile]; }
 
    public:
     /// @brief Gets comparison result
@@ -96,8 +88,8 @@ namespace cbm::qa::checker
     /// @return  Value of comparison result
     CmpResult_t GetCmpResult(int iDS, int iFile, int iObj, int iVer) const
     {
-      int iObjGlob = GetObjects(iFile).begin() - fvObjects.begin() + iObj;
-      int iRes     = iVer + fvVersionLabels.size() * (iObjGlob + iDS * fvObjects.size());
+      int iObjGlob = fvObjectFirstGlobIndex[iFile] + iObj;
+      int iRes     = iVer + fvVersionLabels.size() * (iObjGlob + iDS * fvObjectFirstGlobIndex.back());
       return fvCmpResults[iRes];
     }
 
@@ -157,8 +149,8 @@ namespace cbm::qa::checker
     /// @param value  Value of comparison result
     void SetCmpResult(int iDS, int iFile, int iObj, int iVer, CmpResult_t value)
     {
-      int iObjGlob       = GetObjects(iFile).begin() - fvObjects.begin() + iObj;
-      int iRes           = iVer + fvVersionLabels.size() * (iObjGlob + iDS * fvObjects.size());
+      int iObjGlob       = fvObjectFirstGlobIndex[iFile] + iObj;
+      int iRes           = iVer + fvVersionLabels.size() * (iObjGlob + iDS * fvObjectFirstGlobIndex.back());
       fvCmpResults[iRes] = value;
     }
 
@@ -174,19 +166,31 @@ namespace cbm::qa::checker
     void SetInputRootPath(const char* pathName) { fsInputRootPath = pathName; }
 
    private:
+    /// @brief Reads list of histograms from file
+    /// @param iFile  Index of file
+    /// @note  Accumulates all possible histograms for different datasets
+    void ReadObjectList(int iFile);
+
+    /// @brief Loops over ROOT-file and collects object paths
+    /// @param[in]  pDir        Pointer on directory
+    /// @param[in]  parentPath  Parent path within file
+    /// @param[out] paths       A set of object paths
+    static void CollectObjectPaths(TDirectory* pDir, const TString& parentPah, std::set<std::string>& paths);
+
     int fDefVersionID = -1;  ///< Index of default version
 
     std::string fsInputRootPath = "";  ///< Root path for input files
     std::string fsDefaultLabel  = "";  ///< Name of default version label
 
-    std::vector<std::string> fvDatasets;                    ///< Container of dataset names
-    std::vector<std::string> fvFiles;                       ///< Container of file names
-    std::vector<std::string> fvFileLabels;                  ///< Container of file labels (used in output)
-    std::vector<std::string> fvObjects;                     ///< Container of object names (joint for all the files)
-    std::vector<std::string> fvVersionLabels;               ///< Container of version labels
-    std::vector<std::string> fvVersionPaths;                ///< Container of version paths
-    std::vector<std::pair<int, int>> fvGlobalToFileObject;  ///< Map of global obj. index -> local file-object
-    std::vector<CmpResult_t> fvCmpResults;                  ///< Comparison results vs. dataset, object and version
+    std::vector<std::string> fvDatasets;              ///< Container of dataset names
+    std::vector<std::string> fvFiles;                 ///< Container of file names
+    std::vector<char> fvbProcessWholeFile;            ///< If the whole file should be processed
+    std::vector<int> fvObjectFirstGlobIndex;          ///< First global index of object in a file
+    std::vector<std::string> fvFileLabels;            ///< Container of file labels (used in output)
+    std::vector<std::vector<std::string>> fvObjects;  ///< Container of object names vs file id
+    std::vector<std::string> fvVersionLabels;         ///< Container of version labels
+    std::vector<std::string> fvVersionPaths;          ///< Container of version paths
+    std::vector<CmpResult_t> fvCmpResults;            ///< Comparison results vs. dataset, object and version
   };
 }  // namespace cbm::qa::checker
 
diff --git a/macro/qa/qa_compare_ca.C b/macro/qa/qa_compare_ca.C
index ddb750158a839df51c2040e3433076b142bfa2e9..04541db7dc94d654d88c9dc6972679d2dd95aef6 100644
--- a/macro/qa/qa_compare_ca.C
+++ b/macro/qa/qa_compare_ca.C
@@ -36,7 +36,7 @@ int qa_compare_ca(
   pQaChecker->SetFromYAML(configName);      // Read file-object map
 
   //// ----- Run comparision routine
-  pQaChecker->Process("PRC");  // P -
+  pQaChecker->Process("PRB");  // P -
 
   //// ----- Scan results
   bool res = pQaChecker->Scan();  // true - objects are the same, false - objects differ