Skip to content

Commit 6ba1fef

Browse files
committed
Revert "Bug#37510755 Performance regression in join for tables with many columns"
Change-Id: I162d30d876013e04350eef3d2ebfdc572dfe4f28
1 parent bf8c8bb commit 6ba1fef

File tree

1 file changed

+90
-116
lines changed
  • storage/innobase/rem

1 file changed

+90
-116
lines changed

storage/innobase/rem/rec.h

Lines changed: 90 additions & 116 deletions
Original file line numberDiff line numberDiff line change
@@ -1069,77 +1069,6 @@ static inline enum REC_INSERT_STATE rec_init_null_and_len_comp(
10691069
return (rec_insert_state);
10701070
}
10711071

1072-
/**
1073-
Determine the offset of the given field
1074-
1075-
@param[in] field Field whose length and offset is determined
1076-
@param[in] index Index to which field belongs
1077-
@param[in] temp True for temp record
1078-
@param[in,out] n_null Number of nullable columns in record
1079-
@param[in,out] null_mask Mask of null bitmap
1080-
@param[in,out] nulls Pointer to null bitmap of the record
1081-
@param[in,out] lens Pointer to lens in the record
1082-
@param[in,out] offs Offset of current field, updated to next field
1083-
@param[in,out] any_ext Offset to indicate presence of extern col
1084-
1085-
@return offset Offset of the field
1086-
*/
1087-
static inline uint64_t calculate_field_offset(
1088-
const dict_field_t *field,
1089-
IF_DEBUG(const dict_index_t *index, ) const bool temp, uint16_t &n_null,
1090-
ulint &null_mask, const byte *&nulls, const byte *&lens, ulint &offs,
1091-
ulint &any_ext) {
1092-
/* Fields are stored on disk in version they are added in and are maintained
1093-
in fields_array in the same order. Get the right field. */
1094-
const dict_col_t *col = field->col;
1095-
1096-
if (!(col->prtype & DATA_NOT_NULL)) {
1097-
/* nullable field => read the null flag */
1098-
ut_ad(n_null--);
1099-
1100-
if (UNIV_UNLIKELY(!(byte)null_mask)) {
1101-
nulls--;
1102-
null_mask = 1;
1103-
}
1104-
1105-
if (*nulls & null_mask) {
1106-
null_mask <<= 1;
1107-
/* No length is stored for NULL fields. We do not advance offs, and we set
1108-
the length to zero and enable the SQL NULL flag in offsets[]. */
1109-
return (offs | REC_OFFS_SQL_NULL);
1110-
}
1111-
null_mask <<= 1;
1112-
}
1113-
1114-
if (!field->fixed_len || (temp && !col->get_fixed_size(temp))) {
1115-
ut_ad(col->mtype != DATA_POINT);
1116-
/* Variable-length field: read the length */
1117-
uint64_t len = *lens--;
1118-
/* If the maximum length of the field is up to 255 bytes, the actual length
1119-
is always stored in one byte. If the maximum length is more than 255 bytes,
1120-
the actual length is stored in one byte for 0..127. The length will be
1121-
encoded in two bytes when it is 128 or more, or when the field is stored
1122-
externally. */
1123-
if (DATA_BIG_COL(col)) {
1124-
if (len & 0x80) {
1125-
/* 1exxxxxxx xxxxxxxx */
1126-
len <<= 8;
1127-
len |= *lens--;
1128-
1129-
offs += len & 0x3fff;
1130-
if (UNIV_UNLIKELY(len & 0x4000)) {
1131-
ut_ad(index->is_clustered());
1132-
any_ext = REC_OFFS_EXTERNAL;
1133-
return (offs | REC_OFFS_EXTERNAL);
1134-
}
1135-
return offs;
1136-
}
1137-
}
1138-
return (offs += len);
1139-
}
1140-
return (offs += field->fixed_len);
1141-
}
1142-
11431072
/** Determine the offset to each field in a leaf-page record in
11441073
ROW_FORMAT=COMPACT. This is a special case of rec_init_offsets() and
11451074
rec_get_offsets().
@@ -1198,34 +1127,25 @@ inline void rec_init_offsets_comp_ordinary(const rec_t *rec, bool temp,
11981127
ulint any_ext = 0;
11991128
ulint null_mask = 1;
12001129
uint16_t i = 0;
1201-
1202-
if (rec_insert_state == INSERTED_INTO_TABLE_WITH_NO_INSTANT_NO_VERSION) {
1203-
ut_ad(!index->has_instant_cols_or_row_versions());
1204-
do {
1205-
const dict_field_t *field = index->get_physical_field(i);
1206-
rec_offs_base(offsets)[i + 1] =
1207-
calculate_field_offset(field, IF_DEBUG(index, ) temp, n_null,
1208-
null_mask, nulls, lens, offs, any_ext);
1209-
} while (++i < rec_offs_n_fields(offsets));
1210-
1211-
*rec_offs_base(offsets) = (rec - (lens + 1)) | REC_OFFS_COMPACT | any_ext;
1212-
return;
1213-
}
1214-
1215-
/* This record belongs to a table which has at least one INSTANT ADD/DROP done
1216-
*/
1217-
if (rec_insert_state == INSERTED_BEFORE_INSTANT_ADD_NEW_IMPLEMENTATION) {
1218-
ut_ad(row_version == UINT8_UNDEFINED || row_version == 0);
1219-
ut_ad(index->has_row_versions() || temp);
1220-
/* Record has to be interpreted in v0. */
1221-
row_version = 0;
1222-
}
1223-
12241130
do {
1131+
/* Fields are stored on disk in version they are added in and are
1132+
maintained in fields_array in the same order. Get the right field. */
12251133
const dict_field_t *field = index->get_physical_field(i);
12261134
const dict_col_t *col = field->col;
1135+
uint64_t len;
1136+
12271137
switch (rec_insert_state) {
1228-
case INSERTED_BEFORE_INSTANT_ADD_NEW_IMPLEMENTATION:
1138+
case INSERTED_INTO_TABLE_WITH_NO_INSTANT_NO_VERSION:
1139+
ut_ad(!index->has_instant_cols_or_row_versions());
1140+
break;
1141+
1142+
case INSERTED_BEFORE_INSTANT_ADD_NEW_IMPLEMENTATION: {
1143+
ut_ad(row_version == UINT8_UNDEFINED || row_version == 0);
1144+
ut_ad(index->has_row_versions() || temp);
1145+
/* Record has to be interpreted in v0. */
1146+
row_version = 0;
1147+
}
1148+
[[fallthrough]];
12291149
case INSERTED_AFTER_UPGRADE_BEFORE_INSTANT_ADD_NEW_IMPLEMENTATION:
12301150
case INSERTED_AFTER_INSTANT_ADD_NEW_IMPLEMENTATION: {
12311151
ut_ad(is_valid_row_version(row_version));
@@ -1237,22 +1157,21 @@ inline void rec_init_offsets_comp_ordinary(const rec_t *rec, bool temp,
12371157
column is there in this record or not. */
12381158
if (col->is_dropped_in_or_before(row_version)) {
12391159
/* This columns is dropped before or on this row version so its data
1240-
won't be there on row. So no need to store the length. Instead,
1241-
store offs ORed with REC_OFFS_DROP to indicate the same. */
1242-
rec_offs_base(offsets)[i + 1] = (offs | REC_OFFS_DROP);
1243-
continue;
1244-
1245-
/* NOTE : Existing rows, which have data for this column, would
1246-
still need to process this column, so don't skip and store the
1247-
correct length there. Though it will be skipped while fetching row.
1248-
*/
1160+
won't be there on row. So no need to store the length. Instead, store
1161+
offs ORed with REC_OFFS_DROP to indicate the same. */
1162+
len = offs | REC_OFFS_DROP;
1163+
goto resolved;
1164+
1165+
/* NOTE : Existing rows, which have data for this column, would still
1166+
need to process this column, so don't skip and store the correct
1167+
length there. Though it will be skipped while fetching row. */
12491168
} else if (col->is_added_after(row_version)) {
1250-
/* This columns is added after this row version. In this case no
1251-
need to store the length. Instead store only if it is NULL or
1252-
DEFAULT value. */
1253-
rec_offs_base(offsets)[i + 1] =
1254-
rec_get_instant_offset(index, i, offs);
1255-
continue;
1169+
/* This columns is added after this row version. In this case no need
1170+
to store the length. Instead store only if it is NULL or DEFAULT
1171+
value. */
1172+
len = rec_get_instant_offset(index, i, offs);
1173+
1174+
goto resolved;
12561175
}
12571176
} break;
12581177

@@ -1266,9 +1185,9 @@ inline void rec_init_offsets_comp_ordinary(const rec_t *rec, bool temp,
12661185
/* This would be the case when column doesn't exists in the row. In
12671186
this case we need not to store the length. Instead we store only if
12681187
the column is NULL or DEFAULT value. */
1269-
rec_offs_base(offsets)[i + 1] =
1270-
rec_get_instant_offset(index, i, offs);
1271-
continue;
1188+
len = rec_get_instant_offset(index, i, offs);
1189+
1190+
goto resolved;
12721191
}
12731192

12741193
/* Note : Even if the column has been dropped, this row in V1 would
@@ -1278,9 +1197,64 @@ inline void rec_init_offsets_comp_ordinary(const rec_t *rec, bool temp,
12781197
default:
12791198
ut_ad(false);
12801199
}
1281-
rec_offs_base(offsets)[i + 1] =
1282-
calculate_field_offset(field, IF_DEBUG(index, ) temp, n_null, null_mask,
1283-
nulls, lens, offs, any_ext);
1200+
1201+
if (!(col->prtype & DATA_NOT_NULL)) {
1202+
/* nullable field => read the null flag */
1203+
ut_ad(n_null--);
1204+
1205+
if (UNIV_UNLIKELY(!(byte)null_mask)) {
1206+
nulls--;
1207+
null_mask = 1;
1208+
}
1209+
1210+
if (*nulls & null_mask) {
1211+
null_mask <<= 1;
1212+
/* No length is stored for NULL fields.
1213+
We do not advance offs, and we set
1214+
the length to zero and enable the
1215+
SQL NULL flag in offsets[]. */
1216+
len = offs | REC_OFFS_SQL_NULL;
1217+
goto resolved;
1218+
}
1219+
null_mask <<= 1;
1220+
}
1221+
1222+
if (!field->fixed_len || (temp && !col->get_fixed_size(temp))) {
1223+
ut_ad(col->mtype != DATA_POINT);
1224+
/* Variable-length field: read the length */
1225+
len = *lens--;
1226+
/* If the maximum length of the field is up
1227+
to 255 bytes, the actual length is always
1228+
stored in one byte. If the maximum length is
1229+
more than 255 bytes, the actual length is
1230+
stored in one byte for 0..127. The length
1231+
will be encoded in two bytes when it is 128 or
1232+
more, or when the field is stored externally. */
1233+
if (DATA_BIG_COL(col)) {
1234+
if (len & 0x80) {
1235+
/* 1exxxxxxx xxxxxxxx */
1236+
len <<= 8;
1237+
len |= *lens--;
1238+
1239+
offs += len & 0x3fff;
1240+
if (UNIV_UNLIKELY(len & 0x4000)) {
1241+
ut_ad(index->is_clustered());
1242+
any_ext = REC_OFFS_EXTERNAL;
1243+
len = offs | REC_OFFS_EXTERNAL;
1244+
} else {
1245+
len = offs;
1246+
}
1247+
1248+
goto resolved;
1249+
}
1250+
}
1251+
1252+
len = offs += len;
1253+
} else {
1254+
len = offs += field->fixed_len;
1255+
}
1256+
resolved:
1257+
rec_offs_base(offsets)[i + 1] = len;
12841258
} while (++i < rec_offs_n_fields(offsets));
12851259

12861260
*rec_offs_base(offsets) = (rec - (lens + 1)) | REC_OFFS_COMPACT | any_ext;

0 commit comments

Comments
 (0)