-
Notifications
You must be signed in to change notification settings - Fork 6.1k
bindinfo: add last_used_date to track bindinfo usage frequency #63409
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
Merged
Merged
Changes from all commits
Commits
Show all changes
29 commits
Select commit
Hold shift + click to select a range
3b1610f
bindinfo: add last_used_time to track bindinfo usage frequency
hawkingrei 8860469
update
hawkingrei c51fe2f
update
hawkingrei ba0b7c0
update
hawkingrei 466d5cf
update
hawkingrei 176622b
update
hawkingrei 6df8205
update
hawkingrei 7462747
update
hawkingrei 1a952d7
update
hawkingrei 36db6d1
update
hawkingrei 8eb3832
update
hawkingrei cf3d5a7
update
hawkingrei 6678bef
update
hawkingrei 6f7e7a8
update
hawkingrei 6ea1f17
update
hawkingrei 619bb27
update
hawkingrei 9c66aeb
update
hawkingrei 5d760ec
update
hawkingrei 01bc626
update
hawkingrei fe9c4f5
update
hawkingrei ff9e3a9
update
hawkingrei fedfd53
update
hawkingrei a1ee5d1
update
hawkingrei 7a7835f
update
hawkingrei 78f6098
update
hawkingrei c88e475
update
hawkingrei f8dbbfe
update
hawkingrei 4c8b1d2
update
hawkingrei a45b570
update
hawkingrei File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,124 @@ | ||
| // Copyright 2025 PingCAP, Inc. | ||
| // | ||
| // Licensed under the Apache License, Version 2.0 (the "License"); | ||
| // you may not use this file except in compliance with the License. | ||
| // You may obtain a copy of the License at | ||
| // | ||
| // http://www.apache.org/licenses/LICENSE-2.0 | ||
| // | ||
| // Unless required by applicable law or agreed to in writing, software | ||
| // distributed under the License is distributed on an "AS IS" BASIS, | ||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| // See the License for the specific language governing permissions and | ||
| // limitations under the License. | ||
|
|
||
| package tests | ||
|
|
||
| import ( | ||
| "fmt" | ||
| "testing" | ||
| "time" | ||
|
|
||
| "github.com/pingcap/tidb/pkg/bindinfo" | ||
| "github.com/pingcap/tidb/pkg/testkit" | ||
| "github.com/stretchr/testify/require" | ||
| ) | ||
|
|
||
| func TestBindUsageInfo(t *testing.T) { | ||
hawkingrei marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| checklist := []string{ | ||
| "5ce1df6eadf8b24222668b1bd2e995b72d4c88e6fe9340d8b13e834703e28c32", | ||
| "5d3975ef2160c1e0517353798dac90a9914095d82c025e7cd97bd55aeb804798", | ||
| "9d3995845aef70ba086d347f38a4e14c9705e966f7c5793b9fa92194bca2bbef", | ||
| "aa3c510b94b9d680f729252ca88415794c8a4f52172c5f9e06c27bee57d08329", | ||
| } | ||
| bindinfo.UpdateBindingUsageInfoBatchSize = 2 | ||
| bindinfo.MaxWriteInterval = 100 * time.Microsecond | ||
| store, dom := testkit.CreateMockStoreAndDomain(t) | ||
| bindingHandle := dom.BindingHandle() | ||
| tk := testkit.NewTestKit(t, store) | ||
|
|
||
| tk.MustExec(`use test`) | ||
| tk.MustExec(`set @@tidb_opt_enable_fuzzy_binding=1`) | ||
| tk.MustExec("create table t1(a int, b int, c int, key idx_b(b), key idx_c(c))") | ||
| tk.MustExec("create table t2(a int, b int, c int, key idx_b(b), key idx_c(c))") | ||
| tk.MustExec("create table t3(a int, b int, c int, key idx_b(b), key idx_c(c))") | ||
| tk.MustExec("create table t4(a int, b int, c int, key idx_b(b), key idx_c(c))") | ||
| tk.MustExec("create table t5(a int, b int, c int, key idx_b(b), key idx_c(c))") | ||
|
|
||
| tk.MustExec("prepare stmt1 from 'delete from t1 where b = 1 and c > 1';") | ||
| tk.MustExec("prepare stmt2 from 'delete t1, t2 from t1 inner join t2 on t1.b = t2.b';") | ||
| tk.MustExec("prepare stmt3 from 'update t1 set a = 1 where b = 1 and c > 1';") | ||
| tk.MustExec("execute stmt1;") | ||
| tk.MustExec("create global binding for delete from t1 where b = 1 and c > 1 using delete /*+ use_index(t1,idx_c) */ from t1 where b = 1 and c > 1") | ||
| tk.MustExec("create global binding for delete t1, t2 from t1 inner join t2 on t1.b = t2.b using delete /*+ inl_join(t1) */ t1, t2 from t1 inner join t2 on t1.b = t2.b") | ||
| tk.MustExec("create global binding for update t1 set a = 1 where b = 1 and c > 1 using update /*+ use_index(t1,idx_c) */ t1 set a = 1 where b = 1 and c > 1") | ||
| // cross database binding | ||
| tk.MustExec(`create global binding using select /*+ leading(t1, t2, t3, t4, t5) */ * from *.t1, *.t2, *.t3, *.t4, *.t5`) | ||
| tk.MustExec("select * from t1, t2, t3, t4, t5") | ||
| tk.MustExec("execute stmt1;") | ||
| origin := tk.MustQuery(fmt.Sprintf(`select sql_digest,last_used_date from mysql.bind_info where original_sql != '%s' order by sql_digest`, bindinfo.BuiltinPseudoSQL4BindLock)) | ||
| origin.Check(testkit.Rows( | ||
| "5ce1df6eadf8b24222668b1bd2e995b72d4c88e6fe9340d8b13e834703e28c32 <nil>", | ||
| "5d3975ef2160c1e0517353798dac90a9914095d82c025e7cd97bd55aeb804798 <nil>", | ||
| "9d3995845aef70ba086d347f38a4e14c9705e966f7c5793b9fa92194bca2bbef <nil>", | ||
| "aa3c510b94b9d680f729252ca88415794c8a4f52172c5f9e06c27bee57d08329 <nil>")) | ||
| time.Sleep(50 * time.Microsecond) | ||
| require.NoError(t, bindingHandle.UpdateBindingUsageInfoToStorage()) | ||
| result := tk.MustQuery(fmt.Sprintf(`select sql_digest,last_used_date from mysql.bind_info where original_sql != '%s' order by sql_digest`, bindinfo.BuiltinPseudoSQL4BindLock)) | ||
| t.Log("result:", result.Rows()) | ||
| // The last_used_date should be updated. | ||
| require.True(t, !origin.Equal(result.Rows())) | ||
| var first *testkit.Result | ||
| for range 5 { | ||
| tk.MustExec("execute stmt1;") | ||
| tk.MustExec("execute stmt2;") | ||
| tk.MustExec("execute stmt3;") | ||
| tk.MustExec("select * from t1, t2, t3, t4, t5") | ||
| time.Sleep(1 * time.Second) | ||
| // Set all last_used_date to null to simulate that the bindinfo in storage is not updated. | ||
| resetAllLastUsedData(tk) | ||
| require.NoError(t, bindingHandle.UpdateBindingUsageInfoToStorage()) | ||
| checkBindinfoInMemory(t, bindingHandle, checklist) | ||
| tk.MustQuery(fmt.Sprintf(`select last_used_date from mysql.bind_info where original_sql != '%s' and last_used_date is null`, bindinfo.BuiltinPseudoSQL4BindLock)).Check(testkit.Rows()) | ||
| result := tk.MustQuery(fmt.Sprintf(`select sql_digest,last_used_date from mysql.bind_info where original_sql != '%s' order by sql_digest`, bindinfo.BuiltinPseudoSQL4BindLock)) | ||
| t.Log("result:", result.Rows()) | ||
| if first == nil { | ||
| first = result | ||
| } else { | ||
| // in fact, The result of each for-loop should be the same. | ||
| require.True(t, first.Equal(result.Rows())) | ||
| } | ||
| } | ||
| // Set all last_used_date to null to simulate that the bindinfo in storage is not updated. | ||
| resetAllLastUsedData(tk) | ||
| for range 5 { | ||
| time.Sleep(1 * time.Second) | ||
| // No used, so last_used_date should not be updated. | ||
| require.NoError(t, bindingHandle.UpdateBindingUsageInfoToStorage()) | ||
| tk.MustQuery(`select last_used_date from mysql.bind_info where last_used_date is not null`).Check(testkit.Rows()) | ||
| } | ||
| tk.MustExec("execute stmt1;") | ||
| tk.MustExec("execute stmt2;") | ||
| tk.MustExec("execute stmt3;") | ||
| time.Sleep(1 * time.Second) | ||
| require.NoError(t, bindingHandle.UpdateBindingUsageInfoToStorage()) | ||
| // it has been updated again. | ||
| rows := tk.MustQuery( | ||
| fmt.Sprintf(`select * from mysql.bind_info where original_sql != '%s' and last_used_date is not null`, bindinfo.BuiltinPseudoSQL4BindLock)).Rows() | ||
| require.Len(t, rows, 3) | ||
| } | ||
|
|
||
| func resetAllLastUsedData(tk *testkit.TestKit) { | ||
| tk.MustExec(fmt.Sprintf(`update mysql.bind_info set last_used_date = null where original_sql != '%s'`, bindinfo.BuiltinPseudoSQL4BindLock)) | ||
| } | ||
|
|
||
| func checkBindinfoInMemory(t *testing.T, bindingHandle bindinfo.BindingHandle, checklist []string) { | ||
| for _, digest := range checklist { | ||
| binding := bindingHandle.GetBinding(digest) | ||
| require.NotNil(t, binding) | ||
| lastSaved := binding.UsageInfo.LastSavedAt.Load() | ||
| if lastSaved != nil { | ||
| require.GreaterOrEqual(t, *binding.UsageInfo.LastSavedAt.Load(), *binding.UsageInfo.LastUsedAt.Load()) | ||
| } | ||
| } | ||
| } | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.