Skip to content

Commit cf5e15e

Browse files
AliSQLAliSQL
authored andcommitted
[Feature] Issue#26 ADD SECONDARY CLUSTERING KEY SUPPORT
Description: ------------ 1. Add support for CLUSTERING key type that is a clustering secondary key 2. Add secondary clustering key support to selected places in the query optimizer ported from percona-server: http://bazaar.launchpad.net/~laurynas-biveinis/percona-server/tokudb-multiple-clust-keys/revision/568 http://bazaar.launchpad.net/~laurynas-biveinis/percona-server/tokudb-clustering-query-opt/revision/5695
1 parent 831c22a commit cf5e15e

File tree

15 files changed

+182
-32
lines changed

15 files changed

+182
-32
lines changed

include/my_base.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -260,11 +260,13 @@ enum ha_base_keytype {
260260
#define HA_SPATIAL 1024 /* For spatial search */
261261
#define HA_NULL_ARE_EQUAL 2048 /* NULL in key are cmp as equal */
262262
#define HA_GENERATED_KEY 8192 /* Automaticly generated key */
263+
#define HA_CLUSTERING (1<<31) /* TokuDB CLUSTERING key */
263264

264265
/* The combination of the above can be used for key type comparison. */
265266
#define HA_KEYFLAG_MASK (HA_NOSAME | HA_PACK_KEY | HA_AUTO_KEY | \
266267
HA_BINARY_PACK_KEY | HA_FULLTEXT | HA_UNIQUE_CHECK | \
267-
HA_SPATIAL | HA_NULL_ARE_EQUAL | HA_GENERATED_KEY)
268+
HA_SPATIAL | HA_NULL_ARE_EQUAL | HA_GENERATED_KEY | \
269+
HA_CLUSTERING)
268270

269271
/*
270272
Key contains partial segments.

include/mysql_com.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ enum enum_server_command
125125
#define FIELD_FLAGS_COLUMN_FORMAT 24 /* Field column format, bit 24-25 */
126126
#define FIELD_FLAGS_COLUMN_FORMAT_MASK (3 << FIELD_FLAGS_COLUMN_FORMAT)
127127
#define FIELD_IS_DROPPED (1<< 26) /* Intern: Field is being dropped */
128+
#define CLUSTERING_FLAG (1<< 27) /* Field has a secondary clustering key */
128129

129130
#define REFRESH_GRANT 1 /* Refresh grant tables */
130131
#define REFRESH_LOG 2 /* Start on new log file */

sql/handler.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,7 @@ enum enum_alter_inplace_result {
257257
*/
258258
#define HA_KEY_SCAN_NOT_ROR 128
259259
#define HA_DO_INDEX_COND_PUSHDOWN 256 /* Supports Index Condition Pushdown */
260-
260+
#define HA_CLUSTERED_INDEX 512 /* Data is clustered on this key */
261261

262262

263263
/**
@@ -1010,6 +1010,10 @@ struct handlerton
10101010
// Engine supports foreign key constraint.
10111011
#define HTON_SUPPORTS_FOREIGN_KEYS (1 << 11)
10121012

1013+
/**
1014+
TOKU: Engine supports secondary clustered keys.
1015+
*/
1016+
#define HTON_SUPPORTS_CLUSTERED_KEYS (1 << 12)
10131017

10141018
enum enum_tx_isolation { ISO_READ_UNCOMMITTED, ISO_READ_COMMITTED,
10151019
ISO_REPEATABLE_READ, ISO_SERIALIZABLE};

sql/lex.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ static SYMBOL symbols[] = {
112112
{ "CLASS_ORIGIN", SYM(CLASS_ORIGIN_SYM)},
113113
{ "CLIENT", SYM(CLIENT_SYM)},
114114
{ "CLOSE", SYM(CLOSE_SYM)},
115+
{ "CLUSTERING", SYM(CLUSTERING_SYM)}, /* TokuDB */
115116
{ "COALESCE", SYM(COALESCE)},
116117
{ "CODE", SYM(CODE_SYM)},
117118
{ "COLLATE", SYM(COLLATE_SYM)},

sql/mysqld.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8152,7 +8152,7 @@ SHOW_VAR status_vars[]= {
81528152
{"Table_open_cache_overflows",(char*) offsetof(STATUS_VAR, table_open_cache_overflows), SHOW_LONGLONG_STATUS},
81538153
#ifdef HAVE_MMAP
81548154
{"Tc_log_max_pages_used", (char*) &tc_log_max_pages_used, SHOW_LONG},
8155-
{"Tc_log_page_size", (char*) &tc_log_page_size, SHOW_LONG},
8155+
{"Tc_log_page_size", (char*) &tc_log_page_size, SHOW_LONG_NOFLUSH},
81568156
{"Tc_log_page_waits", (char*) &tc_log_page_waits, SHOW_LONG},
81578157
#endif
81588158
{"Threads_cached", (char*) &blocked_pthread_count, SHOW_LONG_NOFLUSH},

sql/sql_class.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -270,7 +270,8 @@ class Alter_column :public Sql_alloc {
270270

271271
class Key :public Sql_alloc {
272272
public:
273-
enum Keytype { PRIMARY, UNIQUE, MULTIPLE, FULLTEXT, SPATIAL, FOREIGN_KEY};
273+
enum Keytype { PRIMARY= 0, UNIQUE= 1, MULTIPLE= 2, FULLTEXT= 4, SPATIAL= 8,
274+
FOREIGN_KEY= 16, CLUSTERING= 32 };
274275
enum Keytype type;
275276
KEY_CREATE_INFO key_create_info;
276277
List<Key_part_spec> columns;

sql/sql_parse.cc

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6661,11 +6661,19 @@ bool add_field_to_list(THD *thd, LEX_STRING *field_name, enum_field_types type,
66616661
lex->alter_info.key_list.push_back(key);
66626662
lex->col_list.empty();
66636663
}
6664-
if (type_modifier & (UNIQUE_FLAG | UNIQUE_KEY_FLAG))
6664+
if (type_modifier & (UNIQUE_FLAG | UNIQUE_KEY_FLAG | CLUSTERING_FLAG))
66656665
{
6666-
Key *key;
6666+
Key::Keytype keytype;
6667+
if (type_modifier & (UNIQUE_FLAG | UNIQUE_KEY_FLAG))
6668+
keytype= Key::UNIQUE;
6669+
else
6670+
keytype= Key::MULTIPLE;
6671+
if (type_modifier & CLUSTERING_FLAG)
6672+
keytype= (enum Key::Keytype)(keytype | Key::CLUSTERING);
6673+
DBUG_ASSERT(keytype != Key::MULTIPLE);
6674+
66676675
lex->col_list.push_back(new Key_part_spec(*field_name, 0));
6668-
key= new Key(Key::UNIQUE, null_lex_str,
6676+
Key *key= new Key(keytype, null_lex_str,
66696677
&default_key_create_info, 0,
66706678
lex->col_list);
66716679
lex->alter_info.key_list.push_back(key);

sql/sql_planner.cc

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -648,7 +648,8 @@ void Optimize_table_order::best_access_path(
648648
/* Limit the number of matched rows */
649649
tmp= records;
650650
set_if_smaller(tmp, (double) thd->variables.max_seeks_for_key);
651-
if (table->covering_keys.is_set(key))
651+
if (table->covering_keys.is_set(key)
652+
|| (table->file->index_flags(key, 0, 0) & HA_CLUSTERED_INDEX))
652653
{
653654
/* we can use only index tree */
654655
tmp= record_count * table->file->index_only_read_time(key, tmp);
@@ -823,7 +824,8 @@ void Optimize_table_order::best_access_path(
823824

824825
/* Limit the number of matched rows */
825826
set_if_smaller(tmp, (double) thd->variables.max_seeks_for_key);
826-
if (table->covering_keys.is_set(key))
827+
if (table->covering_keys.is_set(key)
828+
|| (table->file->index_flags(key, 0, 0) & HA_CLUSTERED_INDEX))
827829
{
828830
/* we can use only index tree */
829831
tmp= record_count * table->file->index_only_read_time(key, tmp);

sql/sql_select.cc

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2904,6 +2904,27 @@ make_join_readinfo(JOIN *join, ulonglong options, uint no_jbuf_after)
29042904
tab->read_first_record= join_read_first;
29052905
tab->type=JT_INDEX_SCAN; // Read with index_first / index_next
29062906
}
2907+
else if (!(tab->select && tab->select->quick))
2908+
{
2909+
DBUG_ASSERT(table->covering_keys.is_clear_all());
2910+
if (!tab->do_loosescan())
2911+
{
2912+
key_map clustering_keys;
2913+
for (uint i= 0; i < table->s->keys; i++)
2914+
{
2915+
if (tab->keys.is_set(i)
2916+
&& table->file->index_flags(i, 0, 0) & HA_CLUSTERED_INDEX)
2917+
clustering_keys.set_bit(i);
2918+
}
2919+
uint index= find_shortest_key(table, &clustering_keys);
2920+
if (index != MAX_KEY)
2921+
{
2922+
tab->index= index;
2923+
tab->read_first_record= join_read_first;
2924+
tab->type= JT_INDEX_SCAN;
2925+
}
2926+
}
2927+
}
29072928
}
29082929
if (tab->select && tab->select->quick &&
29092930
tab->select->quick->index != MAX_KEY && ! tab->table->key_read)
@@ -3638,13 +3659,14 @@ uint find_shortest_key(TABLE *table, const key_map *usable_keys)
36383659
{
36393660
/*
36403661
If the primary key is clustered and found shorter key covers all table
3641-
fields then primary key scan normally would be faster because amount of
3642-
data to scan is the same but PK is clustered.
3662+
fields and is not clustering then primary key scan normally would be
3663+
faster because amount of data to scan is the same but PK is clustered.
36433664
It's safe to compare key parts with table fields since duplicate key
36443665
parts aren't allowed.
36453666
*/
36463667
if (best == MAX_KEY ||
3647-
table->key_info[best].user_defined_key_parts >= table->s->fields)
3668+
((table->key_info[best].user_defined_key_parts >= table->s->fields)
3669+
&& !(table->file->index_flags(best, 0, 0) & HA_CLUSTERED_INDEX)))
36483670
best= usable_clustered_pk;
36493671
}
36503672
return best;
@@ -4092,7 +4114,8 @@ test_if_skip_sort_order(JOIN_TAB *tab, ORDER *order, ha_rows select_limit,
40924114
(tab->type == JT_ALL &&
40934115
tab->join->primary_tables > tab->join->const_tables + 1) &&
40944116
((unsigned) best_key != table->s->primary_key ||
4095-
!table->file->primary_key_is_clustered()))
4117+
!table->file->primary_key_is_clustered()) &&
4118+
!(best_key >= 0 && (table->file->index_flags(best_key, 0, 0) & HA_CLUSTERED_INDEX)))
40964119
{
40974120
can_skip_sorting= false;
40984121
goto fix_ICP;
@@ -5548,7 +5571,9 @@ test_if_cheaper_ordering(const JOIN_TAB *tab, ORDER *order, TABLE *table,
55485571

55495572
bool is_covering= table->covering_keys.is_set(nr) ||
55505573
(nr == table->s->primary_key &&
5551-
table->file->primary_key_is_clustered());
5574+
table->file->primary_key_is_clustered()) ||
5575+
(table->file->index_flags(nr, 0, 0)
5576+
& HA_CLUSTERED_INDEX);
55525577

55535578
/*
55545579
Don't use an index scan with ORDER BY without limit.

sql/sql_show.cc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1603,6 +1603,8 @@ int store_create_info(THD *thd, TABLE_LIST *table_list, String *packet,
16031603
packet->append(STRING_WITH_LEN("FULLTEXT KEY "));
16041604
else if (key_info->flags & HA_SPATIAL)
16051605
packet->append(STRING_WITH_LEN("SPATIAL KEY "));
1606+
else if (key_info->flags & HA_CLUSTERING) /* TokuDB */
1607+
packet->append(STRING_WITH_LEN("CLUSTERING KEY "));
16061608
else
16071609
packet->append(STRING_WITH_LEN("KEY "));
16081610

@@ -5166,6 +5168,7 @@ static int get_schema_column_record(THD *thd, TABLE_LIST *tables,
51665168
store_column_type(thd, table, field, cs, IS_COLUMNS_DATA_TYPE);
51675169
pos=(uchar*) ((field->flags & PRI_KEY_FLAG) ? "PRI" :
51685170
(field->flags & UNIQUE_KEY_FLAG) ? "UNI" :
5171+
(field->flags & CLUSTERING_FLAG) ? "CLU" : /* TokuDB */
51695172
(field->flags & MULTIPLE_KEY_FLAG) ? "MUL":"");
51705173
table->field[IS_COLUMNS_COLUMN_KEY]->store((const char*) pos,
51715174
strlen((const char*) pos), cs);

0 commit comments

Comments
 (0)