You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@iotdb.apache.org by hu...@apache.org on 2022/08/15 03:30:39 UTC

[iotdb] branch rel/0.13 updated: [To rel/0.13] [IOTDB-2669] C++ client optimize the values type in tablet class (#6811)

This is an automated email from the ASF dual-hosted git repository.

hui pushed a commit to branch rel/0.13
in repository https://gitbox.apache.org/repos/asf/iotdb.git


The following commit(s) were added to refs/heads/rel/0.13 by this push:
     new e9fbaceaa1 [To rel/0.13] [IOTDB-2669] C++ client optimize the values type in tablet class (#6811)
e9fbaceaa1 is described below

commit e9fbaceaa18d0ad1060fff8f40870a762abe5258
Author: liruizhi19 <10...@users.noreply.github.com>
AuthorDate: Mon Aug 15 11:30:34 2022 +0800

    [To rel/0.13] [IOTDB-2669] C++ client optimize the values type in tablet class (#6811)
---
 client-cpp/src/main/Session.cpp                    | 274 +++++++++++++++++----
 client-cpp/src/main/Session.h                      |  34 +--
 client-cpp/src/test/cpp/sessionIT.cpp              |   3 +-
 .../src/AlignedTimeseriesSessionExample.cpp        | 127 ++++++----
 example/client-cpp-example/src/SessionExample.cpp  | 151 +++++++-----
 5 files changed, 416 insertions(+), 173 deletions(-)

diff --git a/client-cpp/src/main/Session.cpp b/client-cpp/src/main/Session.cpp
index b431cd4581..c091eaed6f 100644
--- a/client-cpp/src/main/Session.cpp
+++ b/client-cpp/src/main/Session.cpp
@@ -102,6 +102,112 @@ shared_ptr<TSFetchResultsResp> RpcUtils::getTSFetchResultsResp(const TSStatus &s
     return resp;
 }
 
+void Tablet::createColumns() {
+    for (size_t i = 0; i < schemas.size(); i++) {
+        TSDataType::TSDataType dataType = schemas[i].second;
+        switch (dataType) {
+            case TSDataType::BOOLEAN:
+                values[i] = new bool[maxRowNumber];
+                break;
+            case TSDataType::INT32:
+                values[i] = new int[maxRowNumber];
+                break;
+            case TSDataType::INT64:
+                values[i] = new int64_t[maxRowNumber];
+                break;
+            case TSDataType::FLOAT:
+                values[i] = new float[maxRowNumber];
+                break;
+            case TSDataType::DOUBLE:
+                values[i] = new double[maxRowNumber];
+                break;
+            case TSDataType::TEXT:
+                values[i] = new string[maxRowNumber];
+                break;
+            default:
+                throw UnSupportedDataTypeException(string("Data type ") + to_string(dataType) + " is not supported.");
+        }
+    }
+}
+
+void Tablet::deleteColumns() {
+    for (size_t i = 0; i < schemas.size(); i++) {
+        TSDataType::TSDataType dataType = schemas[i].second;
+        switch (dataType) {
+            case TSDataType::BOOLEAN: {
+                bool* valueBuf = (bool*)(values[i]);
+                delete[] valueBuf;
+                break;
+            }
+            case TSDataType::INT32: {
+                int* valueBuf = (int*)(values[i]);
+                delete[] valueBuf;
+                break;
+            }
+            case TSDataType::INT64: {
+                int64_t* valueBuf = (int64_t*)(values[i]);
+                delete[] valueBuf;
+                break;
+            }
+            case TSDataType::FLOAT: {
+                float* valueBuf = (float*)(values[i]);
+                delete[] valueBuf;
+                break;
+            }
+            case TSDataType::DOUBLE: {
+                double* valueBuf = (double*)(values[i]);
+                delete[] valueBuf;
+                break;
+            }
+            case TSDataType::TEXT: {
+                string* valueBuf = (string*)(values[i]);
+                delete[] valueBuf;
+                break;
+            }
+            default:
+                throw UnSupportedDataTypeException(string("Data type ") + to_string(dataType) + " is not supported.");
+        }
+    }
+}
+
+void Tablet::addValue(int schemaId, int rowIndex, void* value) {
+    TSDataType::TSDataType dataType = schemas[schemaId].second;
+    switch (dataType) {
+        case TSDataType::BOOLEAN: {
+            bool* valueBuf = (bool*)(values[schemaId]);
+            valueBuf[rowIndex] = *((bool*)value);
+            break;
+        }
+        case TSDataType::INT32: {
+            int* valueBuf = (int*)(values[schemaId]);
+            valueBuf[rowIndex] = *((int*)value);
+            break;
+        }
+        case TSDataType::INT64: {
+            int64_t* valueBuf = (int64_t*)(values[schemaId]);
+            valueBuf[rowIndex] = *((int64_t*)value);
+            break;
+        }
+        case TSDataType::FLOAT: {
+            float* valueBuf = (float*)(values[schemaId]);
+            valueBuf[rowIndex] = *((float*)value);
+            break;
+        }
+        case TSDataType::DOUBLE: {
+            double* valueBuf = (double*)(values[schemaId]);
+            valueBuf[rowIndex] = *((double*)value);
+            break;
+        }
+        case TSDataType::TEXT: {
+            string* valueBuf = (string*)(values[schemaId]);
+            valueBuf[rowIndex] = *(string*)value;
+            break;
+        }
+        default:
+            throw UnSupportedDataTypeException(string("Data type ") + to_string(dataType) + " is not supported.");
+    }
+}
+
 void Tablet::reset() {
     rowSize = 0;
     for (int i = 0; i < schemas.size(); i++) {
@@ -110,16 +216,6 @@ void Tablet::reset() {
     }
 }
 
-void Tablet::createColumns() {
-    // create timestamp column
-    timestamps.resize(maxRowNumber);
-    // create value columns
-    values.resize(schemas.size());
-    for (size_t i = 0; i < schemas.size(); i++) {
-        values[i].resize(maxRowNumber);
-    }
-}
-
 int Tablet::getTimeBytesSize() {
     return rowSize * 8;
 }
@@ -143,15 +239,17 @@ int Tablet::getValueByteSize() {
             case TSDataType::DOUBLE:
                 valueOccupation += rowSize * 8;
                 break;
-            case TSDataType::TEXT:
+            case TSDataType::TEXT: {
                 valueOccupation += rowSize * 4;
-                for (const string &value: values[i]) {
-                    valueOccupation += value.size();
+                string* valueBuf = (string*)(values[i]);
+                for (size_t j = 0; j < rowSize; j++) {
+                    valueOccupation += (int)(valueBuf[j].size());
                 }
                 break;
+            }
             default:
                 throw UnSupportedDataTypeException(
-                        string("Data type ") + to_string(schemas[i].second) + " is not supported.");
+                    string("Data type ") + to_string(schemas[i].second) + " is not supported.");
         }
     }
     return valueOccupation;
@@ -173,58 +271,75 @@ string SessionUtils::getValue(const Tablet &tablet) {
     MyStringBuffer valueBuffer;
     for (size_t i = 0; i < tablet.schemas.size(); i++) {
         TSDataType::TSDataType dataType = tablet.schemas[i].second;
-        BitMap *bitMap = tablet.bitMaps[i].get();
-        switch (dataType) {
-            case TSDataType::BOOLEAN:
+        BitMap* bitMap = tablet.bitMaps[i].get();
+        switch (dataType) { 
+            case TSDataType::BOOLEAN: {
+                bool* valueBuf = (bool*)(tablet.values[i]);
                 for (int index = 0; index < tablet.rowSize; index++) {
                     if (!bitMap->isMarked(index)) {
-                        valueBuffer.putBool(tablet.values[i][index] == "true");
-                    } else {
+                        valueBuffer.putBool(valueBuf[index]);
+                    }
+                    else {
                         valueBuffer.putBool(false);
                     }
                 }
                 break;
-            case TSDataType::INT32:
+            }
+            case TSDataType::INT32: {
+                int* valueBuf = (int*)(tablet.values[i]);
                 for (int index = 0; index < tablet.rowSize; index++) {
                     if (!bitMap->isMarked(index)) {
-                        valueBuffer.putInt(stoi(tablet.values[i][index]));
-                    } else {
+                        valueBuffer.putInt(valueBuf[index]);
+                    }
+                    else {
                         valueBuffer.putInt((numeric_limits<int>::min)());
                     }
                 }
                 break;
-            case TSDataType::INT64:
+            }
+            case TSDataType::INT64: {
+                int64_t* valueBuf = (int64_t*)(tablet.values[i]);
                 for (int index = 0; index < tablet.rowSize; index++) {
                     if (!bitMap->isMarked(index)) {
-                        valueBuffer.putLong(stol(tablet.values[i][index]));
-                    } else {
+                        valueBuffer.putLong(valueBuf[index]);
+                    }
+                    else {
                         valueBuffer.putLong((numeric_limits<int64_t>::min)());
                     }
                 }
                 break;
-            case TSDataType::FLOAT:
+            }
+            case TSDataType::FLOAT: {
+                float* valueBuf = (float*)(tablet.values[i]);
                 for (int index = 0; index < tablet.rowSize; index++) {
                     if (!bitMap->isMarked(index)) {
-                        valueBuffer.putFloat(stof(tablet.values[i][index]));
-                    } else {
+                        valueBuffer.putFloat(valueBuf[index]);
+                    }
+                    else {
                         valueBuffer.putFloat((numeric_limits<float>::min)());
                     }
                 }
                 break;
-            case TSDataType::DOUBLE:
+            }
+            case TSDataType::DOUBLE: {
+                double* valueBuf = (double*)(tablet.values[i]);
                 for (int index = 0; index < tablet.rowSize; index++) {
                     if (!bitMap->isMarked(index)) {
-                        valueBuffer.putDouble(stod(tablet.values[i][index]));
-                    } else {
+                        valueBuffer.putDouble(valueBuf[index]);
+                    }
+                    else {
                         valueBuffer.putDouble((numeric_limits<double>::min)());
                     }
                 }
                 break;
-            case TSDataType::TEXT:
+            }
+            case TSDataType::TEXT: {
+                string* valueBuf = (string*)(tablet.values[i]);
                 for (int index = 0; index < tablet.rowSize; index++) {
-                    valueBuffer.putString(tablet.values[i][index]);
+                    valueBuffer.putString(valueBuf[index]);
                 }
                 break;
+            }
             default:
                 throw UnSupportedDataTypeException(string("Data type ") + to_string(dataType) + " is not supported.");
         }
@@ -486,7 +601,28 @@ bool Session::checkSorted(const vector<int64_t> &times) {
     return true;
 }
 
-void Session::sortTablet(Tablet &tablet) {
+template<typename T>
+std::vector<T> sortList(const std::vector<T>& valueList, const int* index, int indexLength) {
+    std::vector<T> sortedValues(valueList.size());
+    for (int i = 0; i < indexLength; i++) {
+        sortedValues[i] = valueList[index[i]];
+    }
+    return sortedValues;
+}
+
+template<typename T>
+void sortValuesList(T* valueList, const int* index, int indexLength) {
+    T* sortedValues = new T[indexLength];
+    for (int i = 0; i < indexLength; i++) {
+        sortedValues[i] = valueList[index[i]];
+    }
+    for (int i = 0; i < indexLength; i++) {
+        valueList[i] = sortedValues[i];
+    }
+    delete[] sortedValues;
+}
+
+void Session::sortTablet(Tablet& tablet) {
     /*
      * following part of code sort the batch data by time,
      * so we can insert continuous data in value list to get a better performance
@@ -500,7 +636,35 @@ void Session::sortTablet(Tablet &tablet) {
     this->sortIndexByTimestamp(index, tablet.timestamps, tablet.rowSize);
     tablet.timestamps = sortList(tablet.timestamps, index, tablet.rowSize);
     for (size_t i = 0; i < tablet.schemas.size(); i++) {
-        tablet.values[i] = sortList(tablet.values[i], index, tablet.rowSize);
+        TSDataType::TSDataType dataType = tablet.schemas[i].second;
+        switch (dataType) {
+            case TSDataType::BOOLEAN: {
+                sortValuesList((bool*)(tablet.values[i]), index, tablet.rowSize);
+                break;
+            }
+            case TSDataType::INT32: {
+                sortValuesList((int*)(tablet.values[i]), index, tablet.rowSize);
+                break;
+            }
+            case TSDataType::INT64: {
+                sortValuesList((int64_t*)(tablet.values[i]), index, tablet.rowSize);
+                break;
+            }
+            case TSDataType::FLOAT: {
+                sortValuesList((float*)(tablet.values[i]), index, tablet.rowSize);
+                break;
+            }
+            case TSDataType::DOUBLE: {
+                sortValuesList((double*)(tablet.values[i]), index, tablet.rowSize);
+                break;
+            }
+            case TSDataType::TEXT: {
+                sortValuesList((string*)(tablet.values[i]), index, tablet.rowSize);
+                break;
+            }
+            default:
+                throw UnSupportedDataTypeException(string("Data type ") + to_string(dataType) + " is not supported.");
+        }
     }
 
     delete[] index;
@@ -558,7 +722,7 @@ Session::putValuesIntoBuffer(const vector<TSDataType::TSDataType> &types, const
                 appendValues(buf, values[i], sizeof(double));
                 break;
             case TSDataType::TEXT: {
-                int len = strlen(values[i]);
+                int len = (int)strlen(values[i]);
                 appendValues(buf, (char *) (&len), sizeof(int));
                 // no need to change the byte order of string value
                 buf.append(values[i], len);
@@ -921,14 +1085,14 @@ void Session::insertRecordsOfOneDevice(const string &deviceId,
     if (!checkSorted(times)) {
         int *index = new int[times.size()];
         for (size_t i = 0; i < times.size(); i++) {
-            index[i] = i;
+            index[i] = (int)i;
         }
 
-        this->sortIndexByTimestamp(index, times, times.size());
-        times = sortList(times, index, times.size());
-        measurementsList = sortList(measurementsList, index, times.size());
-        typesList = sortList(typesList, index, times.size());
-        valuesList = sortList(valuesList, index, times.size());
+        this->sortIndexByTimestamp(index, times, (int)(times.size()));
+        times = sortList(times, index, (int)(times.size()));
+        measurementsList = sortList(measurementsList, index, (int)(times.size()));
+        typesList = sortList(typesList, index, (int)(times.size()));
+        valuesList = sortList(valuesList, index, (int)(times.size()));
         delete[] index;
     }
     TSInsertRecordsOfOneDeviceReq request;
@@ -973,14 +1137,14 @@ void Session::insertAlignedRecordsOfOneDevice(const string &deviceId,
     if (!checkSorted(times)) {
         int *index = new int[times.size()];
         for (size_t i = 0; i < times.size(); i++) {
-            index[i] = i;
+            index[i] = (int)i;
         }
 
-        this->sortIndexByTimestamp(index, times, times.size());
-        times = sortList(times, index, times.size());
-        measurementsList = sortList(measurementsList, index, times.size());
-        typesList = sortList(typesList, index, times.size());
-        valuesList = sortList(valuesList, index, times.size());
+        this->sortIndexByTimestamp(index, times, (int)(times.size()));
+        times = sortList(times, index, (int)(times.size()));
+        measurementsList = sortList(measurementsList, index, (int)(times.size()));
+        typesList = sortList(typesList, index, (int)(times.size()));
+        valuesList = sortList(valuesList, index, (int)(times.size()));
         delete[] index;
     }
     TSInsertRecordsOfOneDeviceReq request;
@@ -1756,3 +1920,17 @@ std::vector<std::string> Session::showMeasurementsInTemplate(const string &templ
     }
     return resp->measurements;
 }
+
+bool Session::checkTemplateExists(const string& template_name) {
+    try {
+        std::unique_ptr<SessionDataSet> dataset;
+        dataset = executeQueryStatement("SHOW NODES IN SCHEMA TEMPLATE " + template_name);
+        bool isExisted = dataset->hasNext();
+        dataset->closeOperationHandle();
+        return isExisted;
+    }
+    catch (exception& e) {
+        std::cout << e.what() << std::endl;
+        throw IoTDBConnectionException(e.what());
+    }
+}
\ No newline at end of file
diff --git a/client-cpp/src/main/Session.h b/client-cpp/src/main/Session.h
index 3a93a8e9af..8377272b21 100644
--- a/client-cpp/src/main/Session.h
+++ b/client-cpp/src/main/Session.h
@@ -311,7 +311,7 @@ public:
     }
 
     void putString(const std::string &ins) {
-        putInt(ins.size());
+        putInt((int)(ins.size()));
         str += ins;
     }
 
@@ -486,11 +486,13 @@ public:
 class Tablet {
 private:
     static const int DEFAULT_SIZE = 1024;
+    void createColumns();
+    void deleteColumns();
 public:
     std::string deviceId; // deviceId of this tablet
     std::vector<std::pair<std::string, TSDataType::TSDataType>> schemas; // the list of measurement schemas for creating the tablet
     std::vector<int64_t> timestamps;   // timestamps in this tablet
-    std::vector<std::vector<std::string>> values; // each object is a primitive type array, which represents values of one measurement
+    std::vector<void*> values; // each object is a primitive type array, which represents values of one measurement
     std::vector<std::unique_ptr<BitMap>> bitMaps; // each bitmap represents the existence of each value in the current column
     int rowSize;    //the number of rows to include in this tablet
     int maxRowNumber;   // the maximum number of rows for this tablet
@@ -525,19 +527,24 @@ public:
                                                         maxRowNumber(maxRowNumber), isAligned(_isAligned) {
         // create timestamp column
         timestamps.resize(maxRowNumber);
-        // create value columns and bitMaps
+        // create value columns
         values.resize(schemas.size());
+        createColumns();
+        // create bitMaps
         bitMaps.resize(schemas.size());
         for (size_t i = 0; i < schemas.size(); i++) {
-            values[i].resize(maxRowNumber);
             bitMaps[i] = std::unique_ptr<BitMap>(new BitMap(maxRowNumber));
         }
         this->rowSize = 0;
     }
 
-    void reset(); // Reset Tablet to the default state - set the rowSize to 0
+    ~Tablet() {
+        deleteColumns();
+    }
 
-    void createColumns();
+    void addValue(int schemaId, int rowIndex, void *value);
+
+    void reset(); // Reset Tablet to the default state - set the rowSize to 0
 
     int getTimeBytesSize();
 
@@ -671,7 +678,7 @@ public:
         this->client = client;
         this->columnNameList = columnNameList;
         this->currentBitmap = new char[columnNameList.size()];
-        this->columnSize = columnNameList.size();
+        this->columnSize = (int)columnNameList.size();
         this->isIgnoreTimeStamp = isIgnoreTimeStamp;
 
         // column name -> column location
@@ -680,7 +687,7 @@ public:
             if (this->columnMap.find(name) != this->columnMap.end()) {
                 duplicateLocation[i] = columnMap[name];
             } else {
-                this->columnMap[name] = i;
+                this->columnMap[name] = (int)i;
                 this->columnTypeDeduplicatedList.push_back(columnTypeList[i]);
             }
             if (!columnNameIndexMap.empty()) {
@@ -724,15 +731,6 @@ public:
     void closeOperationHandle();
 };
 
-template<typename T>
-std::vector<T> sortList(const std::vector<T> &valueList, const int *index, int indexLength) {
-    std::vector<T> sortedValues(valueList.size());
-    for (int i = 0; i < indexLength; i++) {
-        sortedValues[i] = valueList[index[i]];
-    }
-    return sortedValues;
-}
-
 class TemplateNode {
 public:
 
@@ -1152,6 +1150,8 @@ public:
     std::vector<std::string> showMeasurementsInTemplate(const std::string &template_name);
 
     std::vector<std::string> showMeasurementsInTemplate(const std::string &template_name, const std::string &pattern);
+
+    bool checkTemplateExists(const std::string &template_name);
 };
 
 #endif // IOTDB_SESSION_H
diff --git a/client-cpp/src/test/cpp/sessionIT.cpp b/client-cpp/src/test/cpp/sessionIT.cpp
index a011220039..31f5daf0a9 100644
--- a/client-cpp/src/test/cpp/sessionIT.cpp
+++ b/client-cpp/src/test/cpp/sessionIT.cpp
@@ -245,7 +245,8 @@ TEST_CASE("Test insertTablet ", "[testInsertTablet]") {
         int row = tablet.rowSize++;
         tablet.timestamps[row] = time;
         for (int i = 0; i < 3; i++) {
-            tablet.values[i][row] = to_string(i);
+            int64_t randVal = rand();
+            tablet.addValue(i, row, &randVal);
         }
         if (tablet.rowSize == tablet.maxRowNumber) {
             session->insertTablet(tablet);
diff --git a/example/client-cpp-example/src/AlignedTimeseriesSessionExample.cpp b/example/client-cpp-example/src/AlignedTimeseriesSessionExample.cpp
index 25cbed0d49..cdbd1b9dc2 100644
--- a/example/client-cpp-example/src/AlignedTimeseriesSessionExample.cpp
+++ b/example/client-cpp-example/src/AlignedTimeseriesSessionExample.cpp
@@ -23,6 +23,8 @@ using namespace std;
 
 Session *session;
 
+#define DEFAULT_ROW_NUMBER 1000000
+
 void createAlignedTimeseries() {
     string alignedDeviceId = "root.sg1.d1";
     vector<string> measurements = {"s1", "s2", "s3"};
@@ -40,24 +42,26 @@ void createAlignedTimeseries() {
 }
 
 void createSchemaTemplate() {
-    Template temp("template1", false);
+    if (!session->checkTemplateExists("template1")) {
+        Template temp("template1", false);
 
-    InternalNode iNodeD99("d99", true);
+        InternalNode iNodeD99("d99", true);
 
-    MeasurementNode mNodeS1("s1", TSDataType::INT32, TSEncoding::RLE, CompressionType::SNAPPY);
-    MeasurementNode mNodeS2("s2", TSDataType::INT64, TSEncoding::RLE, CompressionType::SNAPPY);
-    MeasurementNode mNodeD99S1("s1", TSDataType::DOUBLE, TSEncoding::RLE, CompressionType::SNAPPY);
-    MeasurementNode mNodeD99S2("s2", TSDataType::BOOLEAN, TSEncoding::RLE, CompressionType::SNAPPY);
+        MeasurementNode mNodeS1("s1", TSDataType::INT32, TSEncoding::RLE, CompressionType::SNAPPY);
+        MeasurementNode mNodeS2("s2", TSDataType::INT64, TSEncoding::RLE, CompressionType::SNAPPY);
+        MeasurementNode mNodeD99S1("s1", TSDataType::DOUBLE, TSEncoding::RLE, CompressionType::SNAPPY);
+        MeasurementNode mNodeD99S2("s2", TSDataType::BOOLEAN, TSEncoding::RLE, CompressionType::SNAPPY);
 
-    iNodeD99.addChild(mNodeD99S1);
-    iNodeD99.addChild(mNodeD99S2);
+        iNodeD99.addChild(mNodeD99S1);
+        iNodeD99.addChild(mNodeD99S2);
 
-    temp.addToTemplate(iNodeD99);
-    temp.addToTemplate(mNodeS1);
-    temp.addToTemplate(mNodeS2);
+        temp.addToTemplate(iNodeD99);
+        temp.addToTemplate(mNodeS1);
+        temp.addToTemplate(mNodeS2);
 
-    session->createSchemaTemplate(temp);
-    session->setSchemaTemplate("template1", "root.sg2");
+        session->createSchemaTemplate(temp);
+        session->setSchemaTemplate("template1", "root.sg2");
+    }
 }
 
 void ActivateTemplate() {
@@ -149,21 +153,24 @@ void insertAlignedRecords() {
 void insertAlignedTablet() {
     pair<string, TSDataType::TSDataType> pairA("s1", TSDataType::INT32);
     pair<string, TSDataType::TSDataType> pairB("s2", TSDataType::DOUBLE);
-    pair<string, TSDataType::TSDataType> pairC("s3", TSDataType::BOOLEAN);
+    pair<string, TSDataType::TSDataType> pairC("s3", TSDataType::DOUBLE);
     vector<pair<string, TSDataType::TSDataType>> schemas;
     schemas.push_back(pairA);
     schemas.push_back(pairB);
     schemas.push_back(pairC);
 
-    Tablet tablet("root.sg1.d1", schemas, 10);
+    Tablet tablet("root.sg2.d2", schemas, 100000);
     tablet.setAligned(true);
 
-    for (int64_t time = 20; time < 30; time++) {
+    for (int64_t time = 0; time < DEFAULT_ROW_NUMBER; time++) {
         int row = tablet.rowSize++;
         tablet.timestamps[row] = time;
-        tablet.values[0][row] = "1";
-        tablet.values[1][row] = "1.0";
-        tablet.values[2][row] = "true";
+        int randVal1 = 123456;
+        double randVal2 = 123456.1234;
+        double randVal3 = 123456.1234;
+        tablet.addValue(0, row, &randVal1);
+        tablet.addValue(1, row, &randVal2);
+        tablet.addValue(2, row, &randVal3);
         if (tablet.rowSize == tablet.maxRowNumber) {
             session->insertTablet(tablet, true);
             tablet.reset();
@@ -185,16 +192,16 @@ void insertAlignedTablets() {
     schemas.push_back(pairB);
     schemas.push_back(pairC);
 
-    Tablet tablet1("root.sg1.d1", schemas, 10);
-    Tablet tablet2("root.sg1.d2", schemas, 10);
-    Tablet tablet3("root.sg1.d3", schemas, 10);
+    Tablet tablet1("root.sg1.d1", schemas, 100);
+    Tablet tablet2("root.sg1.d2", schemas, 100);
+    Tablet tablet3("root.sg1.d3", schemas, 100);
 
     unordered_map<string, Tablet *> tabletMap;
     tabletMap["root.sg1.d1"] = &tablet1;
     tabletMap["root.sg1.d2"] = &tablet2;
     tabletMap["root.sg1.d3"] = &tablet3;
 
-    for (int64_t time = 30; time < 40; time++) {
+    for (int64_t time = 0; time < 20; time++) {
         int row1 = tablet1.rowSize++;
         int row2 = tablet2.rowSize++;
         int row3 = tablet3.rowSize++;
@@ -202,17 +209,26 @@ void insertAlignedTablets() {
         tablet2.timestamps[row2] = time;
         tablet3.timestamps[row3] = time;
 
-        tablet1.values[0][row1] = "1";
-        tablet2.values[0][row2] = "2";
-        tablet3.values[0][row3] = "3";
-
-        tablet1.values[1][row1] = "1.0";
-        tablet2.values[1][row2] = "2.0";
-        tablet3.values[1][row3] = "3.0";
-
-        tablet1.values[2][row1] = "true";
-        tablet2.values[2][row2] = "false";
-        tablet3.values[2][row3] = "true";
+        int randVal11 = rand();
+        int randVal12 = rand();
+        int randVal13 = rand();
+        tablet1.addValue(0, row1, &randVal11);
+        tablet2.addValue(0, row2, &randVal12);
+        tablet3.addValue(0, row3, &randVal13);
+
+        double randVal21 = rand() / 99.9;
+        double randVal22 = rand() / 99.9;
+        double randVal23 = rand() / 99.9;
+        tablet1.addValue(1, row1, &randVal21);
+        tablet2.addValue(1, row2, &randVal22);
+        tablet3.addValue(1, row3, &randVal23);
+
+        bool randVal31 = (bool)(rand() % 2);
+        bool randVal32 = (bool)(rand() % 2);
+        bool randVal33 = (bool)(rand() % 2);
+        tablet1.addValue(2, row1, &randVal31);
+        tablet2.addValue(2, row2, &randVal32);
+        tablet3.addValue(2, row3, &randVal33);
 
         if (tablet1.rowSize == tablet1.maxRowNumber) {
             session->insertAlignedTablets(tabletMap, true);
@@ -233,26 +249,29 @@ void insertAlignedTablets() {
 
 void insertNullableTabletWithAlignedTimeseries() {
     pair<string, TSDataType::TSDataType> pairA("s1", TSDataType::INT32);
-    pair<string, TSDataType::TSDataType> pairB("s2", TSDataType::DOUBLE);
+    pair<string, TSDataType::TSDataType> pairB("s2", TSDataType::INT64);
     pair<string, TSDataType::TSDataType> pairC("s3", TSDataType::BOOLEAN);
     vector<pair<string, TSDataType::TSDataType>> schemas;
     schemas.push_back(pairA);
     schemas.push_back(pairB);
     schemas.push_back(pairC);
 
-    Tablet tablet("root.sg1.d1", schemas, 10);
+    Tablet tablet("root.sg1.d4", schemas, 20);
     tablet.setAligned(true);
 
-    for (int64_t time = 40; time < 50; time++) {
+    for (int64_t time = 0; time < 20; time++) {
         int row = tablet.rowSize++;
         tablet.timestamps[row] = time;
         for (int i = 0; i < 3; i++) {
+            int randVal1 = rand();
+            int64_t randVal2 = rand();
+            bool randVal3 = (bool)(rand() % 2);
             if (i == 0) {
-                tablet.values[i][row] = "1";
+                tablet.addValue(i, row, &randVal1);
             } else if (i == 1) {
-                tablet.values[i][row] = "1.0";
+                tablet.addValue(i, row, &randVal2);
             } else {
-                tablet.values[i][row] = "true";
+                tablet.addValue(i, row, &randVal3);
             }
             // mark null value
             if (row % 3 == i) {
@@ -272,7 +291,7 @@ void insertNullableTabletWithAlignedTimeseries() {
 }
 
 void query() {
-    unique_ptr<SessionDataSet> dataSet = session->executeQueryStatement("select * from root.sg1.d1");
+    unique_ptr<SessionDataSet> dataSet = session->executeQueryStatement("select * from root.sg1.**");
     cout << "timestamp" << "  ";
     for (const string &name: dataSet->getColumnNames()) {
         cout << name << "  ";
@@ -289,14 +308,18 @@ void query() {
 }
 
 void deleteData() {
-    string path = "root.sg1.d1.s1";
+    string path = "root.**";
     int64_t deleteTime = 49;
     session->deleteData(path, deleteTime);
 }
 
 void deleteTimeseries() {
     vector<string> paths;
-    vector<string> alignedTimeseries = {"root.sg1.d1.s1", "root.sg1.d1.s2", "root.sg1.d1.s3"};
+    vector<string> alignedTimeseries = {"root.sg1.d1.s1", "root.sg1.d1.s2", "root.sg1.d1.s3", "root.sg1.d1.s4",
+                                        "root.sg1.d2.s1", "root.sg1.d2.s2", "root.sg1.d2.s3",
+                                        "root.sg1.d3.s1", "root.sg1.d3.s2", "root.sg1.d3.s3",
+                                        "root.sg1.d4.s1", "root.sg1.d4.s2", "root.sg1.d4.s3",
+                                        "root.sg2.d2.s1", "root.sg2.d2.s2", "root.sg2.d2.s3", };
     for (const string &timeseries: alignedTimeseries) {
         if (session->checkTimeseriesExists(timeseries)) {
             paths.push_back(timeseries);
@@ -305,6 +328,14 @@ void deleteTimeseries() {
     session->deleteTimeseries(paths);
 }
 
+void deleteStorageGroups() {
+    vector<string> storageGroups;
+    storageGroups.emplace_back("root.sg1");
+    storageGroups.emplace_back("root.sg2");
+    session->deleteStorageGroups(storageGroups);
+}
+
+
 int main() {
     session = new Session("127.0.0.1", 6667, "root", "root");
 
@@ -344,8 +375,13 @@ int main() {
     cout << "insertAlignedRecords\n" << endl;
     insertAlignedRecords();
 
-    cout << "insertAlignedTablet\n" << endl;
+    cout << "insertAlignedTablet" << endl;
+    cout << "Insert " << DEFAULT_ROW_NUMBER << " records." << endl;
+    time_t now1 = time(0);
     insertAlignedTablet();
+    time_t now2 = time(0);
+    time_t useTime = now2 - now1;
+    cout << "Use time: " << useTime << "s.\n" << endl;
 
     cout << "insertAlignedTablets\n" << endl;
     insertAlignedTablets();
@@ -362,6 +398,9 @@ int main() {
     cout << "deleteTimeseries\n" << endl;
     deleteTimeseries();
 
+    cout << "deleteStorageGroups\n" << endl;
+    deleteStorageGroups();
+
     cout << "session close\n" << endl;
     session->close();
 
diff --git a/example/client-cpp-example/src/SessionExample.cpp b/example/client-cpp-example/src/SessionExample.cpp
index 6d7aa01bab..f33358d3b5 100644
--- a/example/client-cpp-example/src/SessionExample.cpp
+++ b/example/client-cpp-example/src/SessionExample.cpp
@@ -25,15 +25,15 @@ Session *session;
 
 void createTimeseries() {
     if (!session->checkTimeseriesExists("root.sg1.d1.s1")) {
-        session->createTimeseries("root.sg1.d1.s1", TSDataType::INT64, TSEncoding::RLE,
+        session->createTimeseries("root.sg1.d1.s1", TSDataType::BOOLEAN, TSEncoding::RLE,
                                   CompressionType::SNAPPY);
     }
     if (!session->checkTimeseriesExists("root.sg1.d1.s2")) {
-        session->createTimeseries("root.sg1.d1.s2", TSDataType::INT64, TSEncoding::RLE,
+        session->createTimeseries("root.sg1.d1.s2", TSDataType::INT32, TSEncoding::RLE,
                                   CompressionType::SNAPPY);
     }
     if (!session->checkTimeseriesExists("root.sg1.d1.s3")) {
-        session->createTimeseries("root.sg1.d1.s3", TSDataType::INT64, TSEncoding::RLE,
+        session->createTimeseries("root.sg1.d1.s3", TSDataType::FLOAT, TSEncoding::RLE,
                                   CompressionType::SNAPPY);
     }
 
@@ -49,13 +49,13 @@ void createTimeseries() {
 }
 
 void createMultiTimeseries() {
-    if (!session->checkTimeseriesExists("root.sg1.d2.s1") && !session->checkTimeseriesExists("root.sg1.d2.s1")) {
+    if (!session->checkTimeseriesExists("root.sg1.d2.s1") && !session->checkTimeseriesExists("root.sg1.d2.s2")) {
         vector<string> paths;
         paths.emplace_back("root.sg1.d2.s1");
         paths.emplace_back("root.sg1.d2.s2");
         vector<TSDataType::TSDataType> tsDataTypes;
         tsDataTypes.push_back(TSDataType::INT64);
-        tsDataTypes.push_back(TSDataType::INT64);
+        tsDataTypes.push_back(TSDataType::DOUBLE);
         vector<TSEncoding::TSEncoding> tsEncodings;
         tsEncodings.push_back(TSEncoding::RLE);
         tsEncodings.push_back(TSEncoding::RLE);
@@ -86,24 +86,26 @@ void createMultiTimeseries() {
 }
 
 void createSchemaTemplate() {
-    Template temp("template1", false);
+    if (!session->checkTemplateExists("template1")) {
+        Template temp("template1", false);
 
-    InternalNode iNodeD99("d99", false);
+        InternalNode iNodeD99("d99", false);
 
-    MeasurementNode mNodeS1("s1", TSDataType::INT32, TSEncoding::RLE, CompressionType::SNAPPY);
-    MeasurementNode mNodeS2("s2", TSDataType::INT64, TSEncoding::RLE, CompressionType::SNAPPY);
-    MeasurementNode mNodeD99S1("s1", TSDataType::DOUBLE, TSEncoding::RLE, CompressionType::SNAPPY);
-    MeasurementNode mNodeD99S2("s2", TSDataType::BOOLEAN, TSEncoding::RLE, CompressionType::SNAPPY);
+        MeasurementNode mNodeS1("s1", TSDataType::INT32, TSEncoding::RLE, CompressionType::SNAPPY);
+        MeasurementNode mNodeS2("s2", TSDataType::INT64, TSEncoding::RLE, CompressionType::SNAPPY);
+        MeasurementNode mNodeD99S1("s1", TSDataType::DOUBLE, TSEncoding::RLE, CompressionType::SNAPPY);
+        MeasurementNode mNodeD99S2("s2", TSDataType::BOOLEAN, TSEncoding::RLE, CompressionType::SNAPPY);
 
-    iNodeD99.addChild(mNodeD99S1);
-    iNodeD99.addChild(mNodeD99S2);
+        iNodeD99.addChild(mNodeD99S1);
+        iNodeD99.addChild(mNodeD99S2);
 
-    temp.addToTemplate(iNodeD99);
-    temp.addToTemplate(mNodeS1);
-    temp.addToTemplate(mNodeS2);
+        temp.addToTemplate(iNodeD99);
+        temp.addToTemplate(mNodeS1);
+        temp.addToTemplate(mNodeS2);
 
-    session->createSchemaTemplate(temp);
-    session->setSchemaTemplate("template1", "root.sg2");
+        session->createSchemaTemplate(temp);
+        session->setSchemaTemplate("template1", "root.sg2");
+    }
 }
 
 void ActivateTemplate() {
@@ -127,7 +129,7 @@ void showTimeseries() {
 }
 
 void insertRecord() {
-    string deviceId = "root.sg1.d1";
+    string deviceId = "root.sg2.d1";
     vector<string> measurements;
     measurements.emplace_back("s1");
     measurements.emplace_back("s2");
@@ -142,22 +144,29 @@ void insertRecord() {
 }
 
 void insertTablet() {
-    pair<string, TSDataType::TSDataType> pairA("s1", TSDataType::INT64);
-    pair<string, TSDataType::TSDataType> pairB("s2", TSDataType::INT64);
-    pair<string, TSDataType::TSDataType> pairC("s3", TSDataType::INT64);
+    pair<string, TSDataType::TSDataType> pairA("s1", TSDataType::BOOLEAN);
+    pair<string, TSDataType::TSDataType> pairB("s2", TSDataType::INT32);
+    pair<string, TSDataType::TSDataType> pairC("s3", TSDataType::FLOAT);
     vector<pair<string, TSDataType::TSDataType>> schemas;
     schemas.push_back(pairA);
     schemas.push_back(pairB);
     schemas.push_back(pairC);
 
-    Tablet tablet("root.sg1.d1", schemas, 10);
+    Tablet tablet("root.sg1.d1", schemas, 100);
 
-    for (int64_t time = 10; time < 20; time++) {
+    for (int64_t time = 0; time < 30; time++) {
         int row = tablet.rowSize++;
         tablet.timestamps[row] = time;
-        for (int i = 0; i < 3; i++) {
-            tablet.values[i][row] = to_string(i);
-        }
+
+        bool randVal1 = rand() % 2;
+        tablet.addValue(0, row, &randVal1);
+
+        int randVal2 = rand();
+        tablet.addValue(1, row, &randVal2);
+
+        float randVal3 = (float)(rand() / 99.9);
+        tablet.addValue(2, row, &randVal3);
+
         if (tablet.rowSize == tablet.maxRowNumber) {
             session->insertTablet(tablet, true);
             tablet.reset();
@@ -171,7 +180,7 @@ void insertTablet() {
 }
 
 void insertRecords() {
-    string deviceId = "root.sg1.d1";
+    string deviceId = "root.sg2.d1";
     vector<string> measurements;
     measurements.emplace_back("s1");
     measurements.emplace_back("s2");
@@ -182,7 +191,7 @@ void insertRecords() {
     vector<vector<string>> valuesList;
     vector<int64_t> timestamps;
 
-    for (int64_t time = 20; time < 30; time++) {
+    for (int64_t time = 10; time < 30; time++) {
         vector<string> values;
         values.emplace_back("1");
         values.emplace_back("2");
@@ -206,41 +215,49 @@ void insertRecords() {
 
 void insertTablets() {
     pair<string, TSDataType::TSDataType> pairA("s1", TSDataType::INT64);
-    pair<string, TSDataType::TSDataType> pairB("s2", TSDataType::INT64);
-    pair<string, TSDataType::TSDataType> pairC("s3", TSDataType::INT64);
+    pair<string, TSDataType::TSDataType> pairB("s2", TSDataType::DOUBLE);
+    pair<string, TSDataType::TSDataType> pairC("s3", TSDataType::TEXT);
     vector<pair<string, TSDataType::TSDataType>> schemas;
     schemas.push_back(pairA);
     schemas.push_back(pairB);
     schemas.push_back(pairC);
 
-    Tablet tablet1("root.sg1.d1", schemas, 10);
-    Tablet tablet2("root.sg1.d2", schemas, 10);
-    Tablet tablet3("root.sg1.d3", schemas, 10);
+    Tablet tablet1("root.sg1.d2", schemas, 100);
+    Tablet tablet2("root.sg1.d3", schemas, 100);
 
     unordered_map<string, Tablet *> tabletMap;
-    tabletMap["root.sg1.d1"] = &tablet1;
-    tabletMap["root.sg1.d2"] = &tablet2;
-    tabletMap["root.sg1.d3"] = &tablet3;
+    tabletMap["root.sg1.d2"] = &tablet1;
+    tabletMap["root.sg1.d3"] = &tablet2;
 
-    for (int64_t time = 30; time < 40; time++) {
+    for (int64_t time = 0; time < 30; time++) {
         int row1 = tablet1.rowSize++;
         int row2 = tablet2.rowSize++;
-        int row3 = tablet3.rowSize++;
         tablet1.timestamps[row1] = time;
         tablet2.timestamps[row2] = time;
-        tablet3.timestamps[row3] = time;
 
-        for (int i = 0; i < 3; i++) {
-            tablet1.values[i][row1] = to_string(i);
-            tablet2.values[i][row2] = to_string(i);
-            tablet3.values[i][row3] = to_string(i);
-        }
+        int64_t randVal11 = rand();
+        tablet1.addValue(0, row1, &randVal11);
+
+        double randVal12 = rand() / 99.9;
+        tablet1.addValue(1, row1, &randVal12);
+
+        string randVal13 = "string" + to_string(rand());
+        tablet1.addValue(2, row1, &randVal13);
+
+        int64_t randVal21 = rand();
+        tablet2.addValue(0, row2, &randVal21);
+
+        double randVal22 = rand() / 99.9;
+        tablet2.addValue(1, row2, &randVal22);
+
+        string randVal23 = "string" + to_string(rand());
+        tablet2.addValue(2, row2, &randVal23);
+
         if (tablet1.rowSize == tablet1.maxRowNumber) {
             session->insertTablets(tabletMap, true);
 
             tablet1.reset();
             tablet2.reset();
-            tablet3.reset();
         }
     }
 
@@ -248,7 +265,6 @@ void insertTablets() {
         session->insertTablets(tabletMap, true);
         tablet1.reset();
         tablet2.reset();
-        tablet3.reset();
     }
 }
 
@@ -269,13 +285,14 @@ void insertTabletWithNullValues() {
     schemas.push_back(pairB);
     schemas.push_back(pairC);
 
-    Tablet tablet("root.sg1.d1", schemas, 10);
+    Tablet tablet("root.sg1.d4", schemas, 30);
 
-    for (int64_t time = 40; time < 50; time++) {
+    for (int64_t time = 0; time < 30; time++) {
         int row = tablet.rowSize++;
         tablet.timestamps[row] = time;
         for (int i = 0; i < 3; i++) {
-            tablet.values[i][row] = to_string(i);
+            int64_t randVal = rand();
+            tablet.addValue(i, row, &randVal);
             // mark null value
             if (row % 3 == i) {
                 tablet.bitMaps[i]->mark(row);
@@ -298,7 +315,7 @@ void nonQuery() {
 }
 
 void query() {
-    unique_ptr<SessionDataSet> dataSet = session->executeQueryStatement("select s1, s2, s3 from root.sg1.d1");
+    unique_ptr<SessionDataSet> dataSet = session->executeQueryStatement("select s1, s2, s3 from root.**");
     cout << "timestamp" << "  ";
     for (const string &name: dataSet->getColumnNames()) {
         cout << name << "  ";
@@ -322,23 +339,28 @@ void deleteData() {
 
 void deleteTimeseries() {
     vector<string> paths;
-    if (session->checkTimeseriesExists("root.sg1.d1.s1")) {
-        paths.emplace_back("root.sg1.d1.s1");
-    }
-    if (session->checkTimeseriesExists("root.sg1.d1.s2")) {
-        paths.emplace_back("root.sg1.d1.s2");
-    }
-    if (session->checkTimeseriesExists("root.sg1.d1.s3")) {
-        paths.emplace_back("root.sg1.d1.s3");
-    }
-    if (session->checkTimeseriesExists("root.sg1.d1.s4")) {
-        paths.emplace_back("root.sg1.d1.s4");
+    vector<string> timeseriesGrp = { "root.sg1.d1.s1", "root.sg1.d1.s2", "root.sg1.d1.s3", 
+                                    "root.sg1.d2.s1", "root.sg1.d2.s2", "root.sg1.d2.s3", 
+                                    "root.sg1.d3.s1", "root.sg1.d3.s2", "root.sg1.d3.s3",
+                                    "root.sg1.d4.s1", "root.sg1.d4.s2", "root.sg1.d4.s3",
+                                    "root.sg2.d1.s1", "root.sg2.d1.s2", "root.sg2.d1.s3" };
+    for (const string& timeseries : timeseriesGrp) {
+        if (session->checkTimeseriesExists(timeseries)) {
+            paths.push_back(timeseries);
+        }
     }
     session->deleteTimeseries(paths);
 }
 
+void deleteStorageGroups() {
+    vector<string> storageGroups;
+    storageGroups.emplace_back("root.sg1");
+    storageGroups.emplace_back("root.sg2");
+    session->deleteStorageGroups(storageGroups);
+}
+
 void queryLast() {
-    unique_ptr<SessionDataSet> dataSet = session->executeQueryStatement("select last s1,s2,s3 from root.sg1.d1");
+    unique_ptr<SessionDataSet> dataSet = session->executeQueryStatement("select last s1,s2,s3 from root.**");
     for (const string &name: dataSet->getColumnNames()) {
         cout << name << "  ";
     }
@@ -425,6 +447,9 @@ int main() {
     cout << "deleteTimeseries\n" << endl;
     deleteTimeseries();
 
+    cout << "deleteStorageGroups\n" << endl;
+    deleteStorageGroups();
+
     cout << "session close\n" << endl;
     session->close();