tonglin0325的个人主页

MySQL学习笔记——索引原理

1.索引(index)

可以通过在数据库中创建index来加速对表的查询,index可以避免对表的一个全面扫描。对于主键和唯一键,会自动在上面创建索引。

  • 通过使用快速路径访问方法快速定位数据,减少了磁盘的I/O
  • 与表独立存放,但不能独立存在,必须属于某个表
  • 由数据库自动维护,表被删除时,该表上的索引自动被删除

索引的原理:当以某个字段建立一个索引的时候,数据库就会生成一个索引页,索引页不单单保存索引的数据,还保存了索引在数据库的具体的物理地址。

1
2
3
4
5
6
7
8
9
10
11
# 手动创建索引
CREATE INDEX index_tb_dept_name
ON tb_dept(NAME);

# 使用索引,在where之后加上索引,提高查询效率
SELECT * FROM tb_dept WHERE NAME='Tom'

# 重建索引
drop index index_name;
create index index_name on table(column);

注意:如果表的列很少,不适合建立索引。当执行过很多次的insert、delete、update后,会出现索引碎片。影响查询速度,我们应该对索引进行重组。

**索引列最好设置为 NOT NULL**,这通常可以提升查询效率和简化索引操作。

索引失效的场景:

  • 当我们使用左或者左右模糊匹配的时候,也就是 like %xx 或者 like %xx%这两种方式都会造成索引失效;
  • 当我们在查询条件中对索引列做了计算、函数、类型转换操作,这些情况下都会造成索引失效;
  • 联合索引要能正确使用需要遵循最左匹配原则,也就是按照最左优先的方式进行索引的匹配,否则就会导致索引失效。
  • 在 WHERE 子句中,如果在 OR 前的条件列是索引列,而在 OR 后的条件列不是索引列,那么索引会失效。

参考:https://xiaolincoding.com/mysql/index/index_interview.html#有什么优化索引的方法?

https://xiaolincoding.com/mysql/index/index_lose.html#索引失效有哪些?

2.常见索引的种类

主键索引 PRIMARY、唯一索引 UNIQUE、普通索引 INDEX(多字段为组合索引)、全文索引 FULLTEXT、空间索引 SPATIAL

参考:深入理解MySQL索引原理和实现——为什么索引可以加速查询?

1、主键索引

即主索引,根据主键pk_clolum(length)建立索引,不允许重复,不允许空值;

1
2
ALTER TABLE 'table_name' ADD PRIMARY KEY pk_index('col');

全文 >>

Android学习笔记——SQLite

该工程的功能是实现关于数据库的操作,即creat、update、insert、query、delete

调试的时候请用模拟器,用真机调试的时候进入cmd-adb shell,再进入cd data/data的时候会显示permission denied

 

以下的代码是MainActivity.java中的代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
package com.example.sqlite;

import com.example.sqlite.db.DataBaseHelper;

import android.app.Activity;
import android.content.ContentValues;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

public class MainActivity extends Activity {

private Button createDBButton ;
private Button insertDBButton ;
private Button updateDBButton ;
private Button queryDBButton ;
private Button deleteDBButton ;
private EditText input_id ;
private EditText input_name ;
private TextView test ;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//此处为创建数据库, 通过按钮监听器来实现
createDBButton = (Button) findViewById(R.id.creatDB);
createDBButton.setOnClickListener(new CreateDBListener());
//此处为插入数据到数据库中
insertDBButton = (Button) findViewById(R.id.insert);
insertDBButton.setOnClickListener(new InsertListener());
//此处为更新数据表
updateDBButton = (Button) findViewById(R.id.update);
updateDBButton.setOnClickListener(new updateListener());
//此处为更新数据表
queryDBButton = (Button) findViewById(R.id.query);
queryDBButton.setOnClickListener(new queryListener());
//此处为删除数据内容
deleteDBButton = (Button) findViewById(R.id.delete);
deleteDBButton.setOnClickListener(new deleteListener());
//此处为显示查询结果
test = (TextView) findViewById(R.id.result);
test.setText("name") ;
//此处为添加数据的选项
//input_id = (EditText) findViewById(R.id.input_id);
//input_name = (EditText) findViewById(R.id.input_name);
}

class CreateDBListener implements OnClickListener{
@Override
public void onClick(View v) {
// 此处为调用另外一个类中的方法来创建数据库, 或者直接来创建数据库

String db_name = "test_mars_db_one" ;
System.out.println("Create");
DataBaseHelper dbHelper = new DataBaseHelper(MainActivity.this, db_name) ;
SQLiteDatabase db = dbHelper.getReadableDatabase() ;
}
}

class InsertListener implements OnClickListener{

@Override
public void onClick(View v) {
//生成一个ContentValues对象
ContentValues values = new ContentValues() ;
//想该对象当中插入键值对,其中键是列名,值是希望插入到这列的值,值必须
values.put("id", 1) ;
values.put("name", "zhangsan") ;
System.out.println("Insert");
DataBaseHelper dbHelper = new DataBaseHelper(MainActivity.this, "test_mars_db_one") ;
SQLiteDatabase db = dbHelper.getWritableDatabase() ;
//调用insert方法, 就可以将数据插入到数据库中
db.insert("user", null, values) ;
}

}

class updateListener implements OnClickListener{
@Override
public void onClick(View arg0) {
// 此处为更新数据内容
System.out.println("Update");
DataBaseHelper dbHelper = new DataBaseHelper(MainActivity.this, "test_mars_db_one") ;
SQLiteDatabase db = dbHelper.getWritableDatabase() ;
ContentValues values = new ContentValues() ;
values.put("name", "zhangsanfeng") ;
//第一个参数为要更新的表名
//第二个参数为一个ContentValues对象
//第三个参数是where语句
db.update("user", values, "id=?", new String[]{"1"}) ;
}
}


class queryListener implements OnClickListener{
@Override
public void onClick(View v) {
// 此处为查询数据内容, 并用到cursor来实现
System.out.println("query");
DataBaseHelper dbHelper = new DataBaseHelper(MainActivity.this, "test_mars_db_one") ;
SQLiteDatabase db = dbHelper.getWritableDatabase() ;
Cursor cursor = db.query("user", new String[]{"id","name"}, "id=?", new String[]{"2"},null,null,null,null) ;
while(cursor.moveToNext()){
String name = cursor.getString(cursor.getColumnIndex("name")) ;
System.out.print("query---> " + name) ;
//name += name ;
test.setText(name) ;
}
}
}

class deleteListener implements OnClickListener{
public void onClick(View v) {

//此处为实现删除数据
System.out.println("delete");
DataBaseHelper dbHelper = new DataBaseHelper(MainActivity.this, "test_mars_db_one") ;
SQLiteDatabase db = dbHelper.getWritableDatabase() ;

//删除特定条件的数据
//db.delete("user","id=?",new String[]{"2"});
//删除所有数据
db.delete("user",null,null);

}
}

}



 

以下的代码是DataBaseHelper.java中的代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
package com.example.sqlite.db;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteOpenHelper;

//DatabaseHelper作为一个访问SQLite的助手类,提供两个方面的功能
//第一,getReadableDatabase(),getWriteableDatabase()可以获得SQLiteDatabase对象,通过该对象可以对数据库进行操作
//第二,提供了onCreate()和onUpgrade()两个回调函数,允许我们在创建和升级数据库时,进行自己的操作

public class DataBaseHelper extends SQLiteOpenHelper {

private static final int VERSION = 1;
//在SQLiteOpenHelper的子类当中,必须有该构造函数
public DataBaseHelper(Context context, String name, CursorFactory factory,
int version) {
//必须通过super调用父类当中的构造函数
super(context, name, factory, version);
// TODO Auto-generated constructor stub
}

public DataBaseHelper(Context context,String name){
this(context,name,VERSION);
}

public DataBaseHelper(Context context,String name,int version){
this(context,name,null,version);
}

//该函数是在第一次创建数据库的时候执行,实际上是在第一次得到SQLiteDatabase对象的时候,才会调用该方法
@Override
public void onCreate(SQLiteDatabase db) {
// TODO Auto-generated method stub
System.out.println("Create a Database");
//execSQL函数用于执行SQL语句
db.execSQL("create table user(id int,name varchar(20))");
System.out.println("Create a Database successful");
}

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// TODO Auto-generated method stub
System.out.println("update a DataBase");
}

}

 

以下的代码是activity_main.xml中的代码

全文 >>

Android学习笔记——Layout

下面列举了Android中Layout,Table,Menu,Checkbox,Listview,Button,Bundle的基本使用和demo

1.Layout:该工程的功能是实现LinearLayout

Android Layout有多种,比如:Layout,MixLayout,TableLayout等

以下的代码是MainActivity.java中的代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package com.example.linearlayout;

import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.TextView;


public class MainActivity extends Activity {

private TextView firstText;
private TextView secondText;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

firstText = (TextView)findViewById(R.id.firstText);
secondText = (TextView)findViewById(R.id.secondText);

firstText.setText(R.string.firstText);
secondText.setText(R.string.secondText);
}
}

 

以下的代码是activity_main.xml中的代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/LinearLayout1"
android:layout_width="fill_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="${relativePackage}.${activityClass}" >

<!--
android:id 为控件制定相应的ID
android:text 指定控件当中显示的文字
android:gravity 指定控件的基本位置/居中居右等
android:textSize 指定控件的基本位置/居中居右等
android:background 指定该控件所使用的背景色,RGB命名法
android:width 指定控件的宽度
android:height 指定控件的高度
android:padding 指定控件的内边距
android:weight 数字为相应的比例
android:singleLine 设定true为同一行显示
-->



<TextView
android:id="@+id/firstText"
android:gravity="center_vertical"
android:textSize="20pt"
android:background="#0000ff"
android:layout_width="fill_parent"
android:layout_height="0.0dip"
android:paddingLeft="10dip"
android:paddingTop="20dip"
android:paddingRight="30dip"
android:paddingBottom="40dip"
android:layout_weight="1"
android:singleLine="true"
/>

<TextView
android:id="@+id/secondText"
android:gravity="center_vertical"
android:textSize="15pt"
android:background="#00ff00"
android:layout_width="fill_parent"
android:layout_height="0.0dip"
android:paddingLeft="10dip"
android:paddingTop="20dip"
android:paddingRight="30dip"
android:paddingBottom="40dip"
android:layout_weight="2"
android:singleLine="true"
/>

</LinearLayout>

 

以下的代码是string.xml中的代码

1
2
3
4
5
6
7
8
<?xml version="1.0" encoding="utf-8"?>
<resources>

<string name="app_name">LinearLayout</string>
<string name="hello_world">Hello world!</string>
<string name="firstText">第一行</string>
<string name="secondText">第二行</string>
</resources>

全文 >>

Flink学习笔记——Broadcast State

使用broadcast state实现动态配置更新,即双流:一个数据流,一个配置流

1
2
https://flink.apache.org/2019/06/26/broadcast-state.html

可以参考官方文档

1
2
https://ci.apache.org/projects/flink/flink-docs-release-1.13/docs/dev/datastream/fault-tolerance/broadcast_state/

例子:Flink使用Broadcast State实现流处理配置实时更新

 

Mac下安装minikube

1.安装kubectl命令

1
2
brew install kubectl

如果想安装指定版本的kubectl

1
2
3
4
5
curl -LO "https://dl.k8s.io/release/v1.20.0/bin/darwin/amd64/kubectl"
chmod +x ./kubectl
sudo mv ./kubectl /usr/local/bin/kubectl
sudo chown root: /usr/local/bin/kubectl

验证版本,会打印出client端和server端的版本,官方建议2个版本直接版本相差不要大于+/-1

1
2
3
4
kubectl version
Client Version: version.Info{Major:"1", Minor:"20", GitVersion:"v1.20.0", GitCommit:"af46c47ce925f4c4ad5cc8d1fca46c7b77d13b38", GitTreeState:"clean", BuildDate:"2020-12-08T17:59:43Z", GoVersion:"go1.15.5", Compiler:"gc", Platform:"darwin/amd64"}
Server Version: version.Info{Major:"1", Minor:"20", GitVersion:"v1.20.7", GitCommit:"132a687512d7fb058d0f5890f07d4121b3f0a2e2", GitTreeState:"clean", BuildDate:"2021-05-12T12:32:49Z", GoVersion:"go1.15.12", Compiler:"gc", Platform:"linux/amd64"}

  

2.下载和安装minikube

1
2
3
4
5
6
7
8
9
➜  /Users/lintong/Downloads $ curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-darwin-amd64

% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 68.6M 100 68.6M 0 0 9365k 0 0:00:07 0:00:07 --:--:-- 11.0M
➜ /Users/lintong/Downloads $ sudo install minikube-darwin-amd64 /usr/local/bin/minikube

Password:

参考

1
2
https://minikube.sigs.k8s.io/docs/start/

如果要安装指定版本的话,请到下面的地址下载

1
2
https://github.com/kubernetes/minikube/releases

全文 >>

Mac下安装mongodb

1.添加mongo的仓库

1
brew tap mongodb/brew

2.安装mongodb

1
brew install mongodb-community@4.4

参考:Mac OSX 平台安装 MongoDB

安装成功

3.打开mongo shell

1
2
/usr/local/opt/mongodb-community@4.4/bin/mongo xxx:27017/your_db

如果是mongo 6.0的话,是没有mongo命令的,需要额外安装mongosh,下载地址

1
2
https://www.mongodb.com/try/download/shell

4.查询数据

查看db

1
2
show dbs

全文 >>

Spark学习笔记——rdd,dataframe和dataset转换

1.生成RDD

1
2
val rdd: RDD[(String, Int)] = sc.parallelize(Seq(("cat", 30), ("fox", 40)))

2.生成case class RDD

1
2
3
case class WordCount(word: String, count: Long)
val rdd: RDD[WordCount] = sc.parallelize(Seq(WordCount("dog", 50), WordCount("cow", 60)))

3.rdd转df,注意这里需要隐式转换

1
2
3
4
import spark.implicits._

val df = rdd.toDF()

4.rdd转ds,注意 WordCount 需要写在主函数之外

1
2
3
4
import spark.implicits._

val ds: Dataset[WordCount]= rdd.toDS()

5.df转ds

1
2
val ds: Dataset[WordCount]= df.as[WordCount]

6.thrift class rdd转df

1
2
val df = spark.createDataFrame(rdd, classOf[MyBean])

7.thrift class df转ds,需要为thrift class指定encoder

1
2
val ds = df.as[MyBean](Encoders.bean(classOf[MyBean]))

或者

1
2
3
4
implicit val mapEncoder = Encoders.bean(classOf[MyBean])

val ds = df.as[MyBean]

8.avro class rdd转df,参考

1
2
https://stackoverflow.com/questions/47264701/how-to-convert-rddgenericrecord-to-dataframe-in-scala

全文 >>

使用tweak插件修改HTTP请求

tweak是一款可以对request请求的response进行修改的浏览器插件,区别于ModHeader只能对header进行修改,tweak可以对请求的request payload(收费)和response payload(免费)进行拦截和修改。

下图是tweak的界面

同类产品还有requestlytweak的修改HTTP请求response功能是免费的requestly修改API response和request body都是需要收费版本才提供支持

参考:requestly 代理插件

Firefox tweak插件安装地址

https://addons.mozilla.org/en-US/firefox/addon/tweak-extension/

Chrome tweak插件安装地址

https://chromewebstore.google.com/detail/feahianecghpnipmhphmfgmpdodhcapi

全文 >>