2018年9月24日 星期一

MySQL KEY, INDEX

KEY

Key 都會自動建立index
Key可以說是index加上某種限制

PRIMARY KEY

Only one PRIMARY KEY in a table
Value must be unique
Value can not be null
Indexing auto
Primary key允許欄位有null

UNIQUE KEY

Value of column must be unique
Can be null
Indexing auto
Unique key允許欄位有null

CREATE TABLE table_name(
	//...
   UNIQUE KEY(index_column_,index_column_2,...) 
);

//set unique index
CREATE UNIQUE INDEX index_name ON table_name(index_column_1,index_column_2,...);

FOREIGN KEY


Indexing auto
Only references to PRIMARY KEY in another table (NO)

Parameter:
ON DELETE {CASCADE | SET NULL | NO ACTION}
ON UPDATE {CASCADE | SET NULL | NO ACTION | RESTRICT}

Eg.

CREATE TABLE item (
id INT AUTO_INCREMENT,
PRIMARY KEY(id),
user_id INT NOT NULL,
FOREIGN KEY(user_id) REFERENCES user(id) ON DELETE CASCADE ON UPDATE CASCADE);

條件

使用innodb

Eg.

CREATE TABLE product (
prod_id INT NOT NULL,
prod_name CHAR(20),
PRIMARY KEY (prod_id))
ENGINE = INNODB;

CREATE TABLE order (
order_id INT NOT NULL,
prod_id INT,
FOREIGN KEY(prod_id) REFERENCES product(prod_id)
ON DELETE CASCADE
ON UPDATE CASCADE,
PRIMARY KEY (order_id))
ENGINE = INNODB;


設定 foreign key
 order table 的 prod_id 為foreign key

設定參數
ON DELETE CASCADE
ON UPDATE CASCADE

效果
此時如果 delete product table的某筆資料,
也會 delete order 有foreign key參考到的資料。

此時如果update product table的某筆 prod_id,
也會 update order 有foreign key參考到的 prod_id。

此時drop product table 會出錯,因為 order table 參考到它。

FOREIGN KEY 參數說明

[ON DELETE {CASCADE | SET NULL | NO ACTION | RESTRICT}]
[ON UPDATE {CASCADE | SET NULL | NO ACTION | RESTRICT}]

當關聯父資料表的主鍵紀錄行被刪除或修改時,InnoDB 對子資料表中紀錄行的處理方式:

CASCADE - 會將有所關聯的紀錄行也會進行刪除或修改。
SET NULL - 會將有所關聯的紀錄行設定成 NULL。
NO ACTION - 有存在的關聯紀錄行時,會禁止父資料表的刪除或修改動作。
RESTRICT - 與 NO ACTION 相同。

FOREIGN KEY效用

  1. 利用 db schema 防止程式錯誤及阻擋不合法寫入。
  2. 加速 join 效率。

INDEX

參考
Create a indexing data in another table for searching faster.
Index 允許欄位有null
Index 不必要是唯一值

Eg.
CREATE TABLE index_sample(
id INT,
index id_idx(id));

Eg.1
CREATE INDEX index_name ON table_name(column_name(length));

If column is CHAR, VARCHAR type, lenght can less then real length.
If is BLOB or TEXT ,must have length assigned.

Eg.2
ALTER table_name ADD INDEX index_name ON column_name(length))

組合索引

把常用的幾個一起查詢的欄位,建立成一個組合索引,效率更好。

CREATE TABLE my_table(  
id INT NOT NULL,   
user_name VARCHAR(16) NOT NULL,  
city VARCHAR(50) NOT NULL,  
age INT NOT NULL 
);  

//三個欄位建立組合索引
ALTER TABLE my_table ADD INDEX name_city_age (uer_name(10),city,age); 


等於建立以下三個索引
user_name, city, age
user_name, city
user_name
因為索引組合是從最左邊開始的。

以下查詢會用到這個組合索引

SELECT * FROM my_table WHERE user_name="name" AND city="zz"
SELECT * FROM my_table WHERE user_name="abc"
以下查詢不會用到這個組合索引

SELECT * FROM my_table WHERE age=10 AND city="zz"
SELECT * FROM my_table WHERE city="qqq"

INDEX使用時機

Mysql 在以下時機使用

//在 WHERE 中使用
//在 JOIN 中使用
< 
<=
=
>
>=
BETWEEN
IN
及某些LIKE
LIKE "%qee",用%開頭的LIKE不會用索引
LIKE "qee%"這樣會用

以下要對city 及 age建立索引,
my_table的user_name也要。

SELECT t.Name 
FROM my_table t LEFT JOIN my_table m   
ON t.Name=m.user_name WHERE m.age=20 AND m.city="xxx" 




索引的缺點

  • 索引加快搜尋速度,降低更改速度。因為INSERT, UPDATE, DELETE也要更新索引。
  • 索引會佔用一點空間。

使用索引注意事項,以下不會使用索引

  • 當mysql優化器判斷全表掃描比索引快
  • 索引不會包含有NULL的欄位
  • 多使用短索引
  • 不鼓勵使用LIKE
  • 不要在SQL語句上計算
  • 不要在SQL語句上使用函數運算
//這樣有計算
select * from users where YEAR(adddate)

//改成這樣
select * from users where adddate<‘2007-01-01’
  • 不使用NOT IN 和 <>
  • 類型錯誤
  • //假設 X type 是 char
    select * from users where X =1
    
    //改成這樣
    select * from users where X ='1'
    

強制使用索引

force index 索引名

優化

my.cnf 中的 key_buffer 值能夠把所有索引容納進去最好
SQL 指令前加上 explain 來顯示該 SQL 是否用到索引

2018年9月18日 星期二

MySQL 8.0 更改為native password 及 忘記密碼重設



更改為native password

[mysqld]
default-authentication-plugin=mysql_native_password

新的
default-authentication-plugin=caching_sha2_password

這樣子沒用,會造成原本的root無法登入。
mysql> alter user 'root'@'localhost' identified with mysql_native_password by 'password';


移除password validate 


UNINSTALL COMPONENT 'file://component_validate_password';


重設密碼


Stop the MySQL server if necessary, then restart it with the --skip-grant-tables
shell> mysql
mysql> FLUSH PRIVILEGES;
mysql> ALTER USER 'root'@'localhost' IDENTIFIED BY 'MyNewPass';

2018年9月17日 星期一

Homebrew

Command

Package


Package installed Path

/user/local/Cellar/

List installed package

brew list

List target package

brew list mysql

Install package of latest version 

brew install mysql

Install package of target version

brew install mysql@5.6

Unlink now package

brew unlink mysql@5.6

Switch to new package

brew switch <formula><version>
brew switch mysql 8.0.12

Check current linked package

ls /usr/local/Cellar/<package>
ls /usr/local/Cellar/mysql

List which version of package is currently symlinked

ls -l /usr/local/bin/msyql  => ../Cellar/mysql56/5.6.27/bin/mysql

Service


Install brew services

brew tab homebrew/services

Start/stop a service

sudo brew services start mysql
sudo brew services stop mysql

is equal to:
* ln -sfv /usr/local/opt/mysql/*.plist ~/Library/LaunchAgents
* launchctl load ~/Library/LaunchAgents/homebrew.mxcl.mysql.plist

List installed services

brew services list

Run but not a background service

mysql.server start

List services

brew services list

MySQL

homebrew github

裝多份mysql 出現 connect /tmp/mysql.sock  error

裝多個版本

Start mysql as service

sudo brew services start mysql
sudo brew services stop mysql

Run but not a background service


mysql.server start

重複裝 出現connect /tmp/mysql.sock error,

先把之前的data folder 刪掉,
unlink,移除再重裝(或 reinstall)


2018年9月10日 星期一

Goland mac delve problem

Debug時錯誤

Error:could not launch process: EOF
Reason:goland使用內建的dlv,版本太舊,改用新的就可以了。

1 brew安裝delve

https://github.com/go-delve/homebrew-delve

2 goland 指定使用自己安裝的delve

選單 Help / Edit custom properties...
dlv.path=/Users/cruise/go/bin/dlv

2018年8月5日 星期日

OOP的五個原則

1. S Single Responsibility Principle (SRP) 單一職責
2. O Open Closed Principle (OCP)           開放封閉
3. L Liskov’s Substitution Principle (LSP) 里氏替換原則
4. I Interface Segregation Principle (ISP) 介面隔離
5. D Dependency Inversion Principle (DIP)  依賴倒轉

各原則是相通且相輔相成的。(廢話,各原則當然不可能互相抵觸。)

某原則可能是其他原則的基礎。

因為注重『單一職責』,程式碼才容易維持『開放封閉』。

因為『里氏替換原則』,才能用替換子物件的方式擴充功能(開放封閉)。

因為『介面隔離』,每個物件遵循各自介面,才能『依賴倒轉』。

Single Responsibility Principle
單一職責原則 / 只能有單一原因去更改類別

  • There should never be more than one reason for a class to change.
  • 每個類別(或者模組)只能有一種原因去改變它。意即每個類別只負責一個職責。
原則很簡單,但是職責的劃分很難。

原文由Robert C. Martin在《敏捷軟體開發,原則,模式和實踐》一書提出。

Robert C. Martin把職責定義為「改變的原因」。職責從另一個角度,就是改變的原因。也許從這個角度看,比較容易劃分。

書中範例:
一個用於編輯和列印報表的類別,有兩種原因會改變它,一個是因為報表內容改變,一個是報表格式改變。這兩種原因有本質上的不同,

所以應區分為兩個類。否則會因為改動其中一個原因而影響另一個。

設計類別(模組)時,要思考,之後只能因為一種原因而改變這個類別的內容。
如果你只會因為一種原因改變它,那它自然就只有一種職責。
從這個角度去思考職責劃分,就比較容易了。

範例武器系統:
遊戲的武器系統模組有「強化」「進階」等功能。每個都應該是一個單一模組。
兩個功能對象都是武器,可能輸入的是相同資料。
如果企劃更改「強化」效果,就要改模組。但「強化」跟「進階」是各自獨立的,所以設計成單一模組。

Open Closed Principle
開放封閉原則

  • Software entities (classes, modules, functions) should be open for extension but closed for modification.
  • 軟體實體(包括類別,模組,函式等)應讓外部能擴展自己的功能,
但對外關閉修改功能。

外部透過繼承等方式,擴充某實體的功能。關鍵字是:擴展。
外部不能修改它原本的功能。關鍵字是:修改。

垂直擴展:
實作上使用介面的方式,定義出開放的部分。繼承者實作介面,然後加讓自己的功能,可達到垂直擴展。

橫向擴展:
新的實體實作相同的介面,裡面提供不同的功能,就能達到橫向擴展。

橫向擴展:
一個實體實作了兩組介面,就能成為兩組繼承鏈的橋樑,達到橫向擴展。

除開放的介面外,其餘一律不跟外界接觸,達到修改封閉。

Lislov's Substitution Principle
里氏替換原則

  • Let q(x) be a property provable about objects x of type T. Then q(y) should be true for objects y of type S where S is a subtype of T.
  • 物件的父類可被其子類替換,而程式行為並無改變。
因為可替換,才延伸出可用子類擴充父類的功能。

因為雙方依賴於抽象層,於是可替換。

Interface Segregation Principle
介面隔離原則

  • Clients should not be forced to depend upon interfaces that they don't use.
  • The dependency of one class to another one should depend on the smallest possible interface。
  • 實作端不應被強迫依賴於它們用不到的介面上。
  • 一個類別依賴於另一個,最好只依賴於最少的介面上。
依賴於用不到的介面,就增加了耦合度,增加未來修改的負擔。總之就是依賴越小越好。

類別依賴於另一類別的介面上,也是越少越好,少到只要能滿組自己需求即可。

『單一職責』告訴我們未來修改的原因只能有一個,因此它不可能有太多功能,意即它只需依賴少少的介面。

介面設計時應區分出來,讓每個類別不碰到不需要的介面。

因為都依賴於抽象層,所以抽象層要劃分的小一點,否則就失去這些原則的功能了。

Dependency Inversion Principle
依賴倒轉原則


  • A high level module should not depend on low level modules. Both should depend on abstractions.
  • Abstractions should not depend on details. Details should depend on abstractions.
  • 高層模組不依賴於低層模組(例如某函式庫),兩者應透過抽象層溝通。例如兩者可透過中間定義的介面來溝通。
  • 抽象不依賴於細節(實作),細節依賴於抽象,其實跟上面同樣意思。兩者的原則都是要依賴於抽象(某介面)。

相互之間只依賴於介面,誰也不依賴另一方,雙方可以獨立修改,才能做到其他原則。

才能開放-封閉。各自內部修改,透過介面對外開放。子物件只要遵循相同介面,就能擴充功能。

中文翻譯的不好,讓人看不懂。個人的理解是透過抽象介面解除依賴,理解成『依賴解除』好點。

2018年7月26日 星期四

實作每秒千萬級別的訊息發送系統

場景

網路協議:       TCP/IP
網路程式介面: socket
CCU:            1000,000
每秒發送訊息次數: 10
總訊息傳送次數:    1000,000*10=10,000,000

瓶頸

linux內核
每秒送出的TCP/IP封包次數上限約 10,000,000/sec

鎖
要遍歷全部的連線,一個一個發送訊息,所以需要加鎖。
數量高達1000,000,所以這個過程很久,導致其他操作無法執行。
例如login,logout,都要等全部發送完解鎖後,才能執行。

頻寬
頻寬約需400MB-600MB之間。

解法

針對linux內核發送TCP/IP封包次數上限瓶頸
減少發送次數,一秒內的訊息,全部組合成一個訊息,統一發送。

針對鎖的瓶頸
把1000,000連線,分拆為多個集合,用併發的方式同步處理,
可有效減少上鎖時間。
鎖用讀寫鎖,不用互斥鎖。

針對頻寬瓶頸
訊息壓鎖。
換1GB網卡,加大頻寬。

單機架構



分散架構

2018年7月25日 星期三

MySQL 輸出結果到檔案


範例

select * from table_name
INTO OUTFILE '/directory/output.csv'
FIELDS TERMINATED BY ','
ENCLOSED BY '"'
LINES TERMINATED BY '\n'


以上執行select * from table_name 輸出到 '/directory/output.csv',
以逗號為欄位的分隔符號,然後每個欄位資料以雙引號刮起來,
每筆資料結尾以 '\n' 結束。