-
Notifications
You must be signed in to change notification settings - Fork 5.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
ddl: support add global index operation on partition table #18402
Conversation
@@ -971,8 +971,8 @@ func GenIndexKey(sc *stmtctx.StatementContext, tblInfo *model.TableInfo, idxInfo | |||
} | |||
|
|||
// GenIndexValue creates encoded index value and returns the result | |||
func GenIndexValue(sc *stmtctx.StatementContext, tblInfo *model.TableInfo, idxInfo *model.IndexInfo, | |||
containNonBinaryString bool, distinct bool, untouched bool, indexedValues []types.Datum, h kv.Handle) ([]byte, error) { | |||
func GenIndexValue(sc *stmtctx.StatementContext, tblInfo *model.TableInfo, idxInfo *model.IndexInfo, containNonBinaryString bool, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If there are multiple reference of this function in other packages, it's better to introduce a new function such as GenGlobalIndexValue
instead of changing the API
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This API does not change, I just split a long single line into two.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You add a partitionID int64
, right?
ddl/db_test.go
Outdated
c.Assert(rowValueDatums[cols[1].ID], DeepEquals, types.NewDatum(1)) | ||
|
||
// check row 2 | ||
key, _, err = tablecodec.GenIndexKey(sc, tblInfo, indexInfo, tblInfo.ID, []types.Datum{types.NewDatum(2)}, kv.IntHandle(1), nil) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
check row1 and row2 code are basically the same, you could define a local function to reduce repeat code.
@@ -971,8 +971,8 @@ func GenIndexKey(sc *stmtctx.StatementContext, tblInfo *model.TableInfo, idxInfo | |||
} | |||
|
|||
// GenIndexValue creates encoded index value and returns the result | |||
func GenIndexValue(sc *stmtctx.StatementContext, tblInfo *model.TableInfo, idxInfo *model.IndexInfo, | |||
containNonBinaryString bool, distinct bool, untouched bool, indexedValues []types.Datum, h kv.Handle) ([]byte, error) { | |||
func GenIndexValue(sc *stmtctx.StatementContext, tblInfo *model.TableInfo, idxInfo *model.IndexInfo, containNonBinaryString bool, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You add a partitionID int64
, right?
I'm not sure the quite sure the influence of alter table add primary key on the global index encoding. |
PTAL @wjhuang2016 @crazycs520 |
table/tables/index.go
Outdated
// | | | | ||
// | | | The length >= 19 always because of padding. | ||
// | | | | ||
// ... (Truncated because of length.) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why truncated?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
New layout of local index is just add 8 bytes partitionID at the end, rest part is same as local index . I think 2 examples is enough. If write whole layout here, it seems too long.
ddl/db_integration_test.go
Outdated
@@ -1169,7 +1169,7 @@ func (s *testIntegrationSuite5) TestBackwardCompatibility(c *C) { | |||
TableID: tbl.Meta().ID, | |||
Type: model.ActionAddIndex, | |||
BinlogInfo: &model.HistoryInfo{}, | |||
Args: []interface{}{unique, indexName, indexPartSpecifications, indexOption}, | |||
Args: []interface{}{unique, false, indexName, indexPartSpecifications, indexOption}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This may cause a problem when rolling upgrades. A new TiDB receives old args sent by old TiDB.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a better way to pass one more arg to worker? I have no idea.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Put it in the last arg
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add new field in model.IndexInfo is backward compatible, i.e. a newer TiDB can handle older TiDB.
When the new version find the Global
field is missing (by old TiDB), it set the value to false.
A old TiDB receive newer TiDB may be something wrong, because Global
may be true and the old server do not know how to handle it, so we must gurantee there is no DDL during rolling update.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please fire a proposal first. We need to understand and check the whole design before reviewing it.
Appending a new element to the end of the value is not extensible. |
I write the proposal in a new PR. |
LGTM |
maybe we want to support create global in create table stmt in following PR~? for example:
|
indexColumns, err := buildIndexColumns(append(tblInfo.Columns, hiddenCols...), indexPartSpecifications) | ||
if err != nil { | ||
return errors.Trace(err) | ||
} | ||
|
||
global := false | ||
if unique && tblInfo.GetPartitionInfo() != nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
tiny requirement question:
do we need support non-unique global index?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe it's useful to support "using a non-unique index without include partition columns", maybe there is a real-world example:
create table order (
oid_id int,
user_id int,
seller_id int,
primary key(oid, user_id),
index uid (user_id),
) partition by hash(user_id) partition 1000
this table will conventional in the "user end side" to let the order-system query by user_id
.
but the seller also want query the orders belongs itself in seller system and delivery order, and query by seller_id
and it didn't know partition_id(also seller_id isn't unique in order table), and maybe we need a global non-unique index --- index sid (seller_id)
to help seller request can be prunning?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not in this PR.
Support global unique index is complex enough, we should do it step by step.
LGTM PTAL @coocood @wjhuang2016 |
/merge |
@tiancaiamao Oops! This PR requires at least 2 LGTMs to merge. The current number of |
LGTM |
/merge |
/run-all-tests |
@ldeng-ustc merge failed. |
/run-unit-test |
What problem does this PR solve?
Problem Summary:
Support adding global indices. It is a part of #18032 .
What is changed and how it works?
Proposal: #18982
What's Changed:
When global index is enabled, constraint in partition table index will be removed. If
config.EnableGlobalIndex
is set, user can add global index by adding an index which value columns do not include all partition columns.such as:
Before this PR:
After (set
EnableGlobalIndex
):How it Works:
model.IndexInfo
was modified to addGlobal
field in paser PR #917.Decide whether index is global before ddl job is enqueued.
In global index,
tableID
(i.e.TableInfo.ID
) instead ofphysicalTableID
was used to create index prefix, meanwhile,partitionID
is add into value layout.tablecodec.GenIndexValueNew
support encode global index value.Finally, add a testcase to test whether data is correctly writed into kv.
Index Value Layout
Now, we have 6 index value layouts, and use 3 different function to decode it. This not only makes it hard to add new features for index (we should add at least two layouts and one function), but also makes the code and comments less readable and confusing (
index.Create
has an extreme long comment, and is still getting longer).In fact, we can just divide the encoding into two layout: new and old. Old encoding value has no specific part, and length always <= 9. On the other hand, new encoding value has >= 10 length, and include some segments for specific features (e.g. restoreData for new collation, common handle, and also, partitionID for global index).
So, I refactor
tablecodec.GenIndexValue
andtablecodec.DecodeIndexKV
for extensibilty, and rewrite comment ofindex.Create
in a more readable way. After that, we can easily add new features to index value: simply add a segment to value.Here is the new description of index value layout. Note that I just change the decription, so this encoding is exactly same as origin (expect additional global index segment). In other words, there is no compatibility issue.
Related changes
pingcap/parser
: #917Check List
Tests
Side effects
Release note