MCPcopy Create free account
hub / github.com/apple/foundationdb / set

Method set

fdbserver/KeyValueStoreSQLite.actor.cpp:796–895  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

794 }
795 void remove() { db.checkError("BtreeDelete", sqlite3BtreeDelete(cursor)); }
796 void set(KeyValueRef kv) {
797 if (db.fragment_values) {
798 // Unlike a read, where we need to access fragments in fully forward or reverse order,
799 // here we just want to delete any existing fragments for the key. It does not matter
800 // what order we delete them in, and SQLite requires us to seek after every delete, so
801 // the fastest way to do this is to repeatedly seek to the tuple prefix (key, ) and
802 // delete the current fragment until nothing is there.
803 // This should result in almost identical performance to non-fragmenting mode for single fragment kv pairs.
804 int seekResult = moveTo(kv.key, true); // second arg means to ignore fragmenting and seek to (key, )
805 while (seekResult == 0) {
806 remove();
807 seekResult = moveTo(kv.key, true);
808 }
809
810 const int primaryPageUsable = SERVER_KNOBS->SQLITE_FRAGMENT_PRIMARY_PAGE_USABLE;
811 const int overflowPageUsable = SERVER_KNOBS->SQLITE_FRAGMENT_OVERFLOW_PAGE_USABLE;
812
813 int fragments = 1;
814 int valuePerFragment = kv.value.size();
815
816 // Figure out if we would benefit from fragmenting this kv pair. The key size must be less than
817 // primary page usable size, and the value and key size together must exceeed the primary page usable size.
818 if ((kv.key.size() + kv.value.size()) > primaryPageUsable && kv.key.size() < primaryPageUsable) {
819
820 // Just the part of the value that would be in a partially-filled overflow page
821 int overflowPartialBytes = (kv.expectedSize() - primaryPageUsable) % overflowPageUsable;
822
823 // Number of bytes wasted in the unfragmented case
824 int unfragmentedWaste = overflowPageUsable - overflowPartialBytes;
825
826 // Total space used for unfragmented form
827 int unfragmentedTotal = kv.expectedSize() + unfragmentedWaste;
828
829 // Value bytes that can fit in the primary page for each fragment
830 int primaryPageValueBytes = primaryPageUsable - kv.key.size();
831
832 // Calculate how many total fragments it would take to spread the partial overflow page bytes and the
833 // first fragment's primary page value bytes evenly over multiple tuples that fit in primary pages.
834 fragments =
835 (primaryPageValueBytes + overflowPartialBytes + primaryPageValueBytes - 1) / primaryPageValueBytes;
836
837 // Number of bytes wasted in the fragmented case (for the extra key copies)
838 int fragmentedWaste = kv.key.size() * (fragments - 1);
839
840 // Total bytes used for the fragmented case
841 // int fragmentedTotal = kv.expectedSize() + fragmentedWaste;
842
843 // Calculate bytes saved by having extra key instances stored vs the original partial overflow page
844 // bytes.
845 int savings = unfragmentedWaste - fragmentedWaste;
846
847 double reduction = (double)savings / unfragmentedTotal;
848
849 // printf("K: %5d V: %6d OVERFLOW: %5d FRAGMENTS: %3d SAVINGS: %4d FRAG: %7d UNFRAG: %7d
850 // REDUCTION: %.3f\n", kv.key.size(), kv.value.size(), overflowPartialBytes, fragments, savings,
851 // fragmentedTotal, unfragmentedTotal, reduction);
852 if (reduction < SERVER_KNOBS->SQLITE_FRAGMENT_MIN_SAVINGS)
853 fragments = 1;

Callers

nothing calls this directly

Calls 10

moveToFunction · 0.85
sqlite3BtreeInsertFunction · 0.85
substrMethod · 0.80
removeFunction · 0.70
encodeFunction · 0.70
KeyValueRefClass · 0.50
sizeMethod · 0.45
expectedSizeMethod · 0.45
checkErrorMethod · 0.45
beginMethod · 0.45

Tested by

no test coverage detected