Mysql 之 入門一篇搞定

數據庫分類

列式數據庫 按列存儲,方便查找,但是隨着內存和SSD壓縮列所佔百分比的提高,它也可以用來事務處理和數據更新。適合大量數據。
優點:
1.極高的裝載速度 (最高可以等於所有硬盤IO 的總和)
2.適合大量的數據而不是小數據
3.高效的壓縮率,不僅節省儲存空間也節省計算內存和CPU. 4.非常適合做聚合操作
缺點:
1.不適合隨機更新
2.不適合含有刪除和更新的實時操作
行式數據庫 按行存儲,便於事務處理

安裝

下載

https://downloads.mysql.com/archives/community/

選擇你需要的版本,下載源碼,編譯安裝

安裝

centos7 源碼編譯安裝 mysql5.7

存儲引擎對比

MyISAM InnoDB NDBCluster
特點:
1.不支持事務
2.表級鎖定,限制了併發
3.讀寫互相阻塞(即讀取時阻塞寫,寫時阻塞讀)
4.只會用key_buffer緩存索引
1.支持4個事務隔離級別
2.行級鎖定
3.讀寫阻塞與事務隔離級別相關
4.高效緩存,整個表和主鍵以cluster方式存儲,組成一顆平衡樹
1.分佈式存儲引擎,存儲整體中的部分數據
2.支持事務
3.內存需求巨大
適用場合:
1.不需要支持事務
2.併發相對較低
3.數據修改較少
4.以讀爲主
5.數據一致性要求不是非常高 對於相對靜態的數據,利用query cache可以極大提高訪問效率
1.事務支持
2.高併發支持,但注意查詢用索引
3.數據更新較爲頻繁
4.數據一致性要求高 避免全表掃描 大數據插入自己控制事務 避免主鍵更新
1.非常高併發需求
2.對單個請求響應不嚴格
3.查詢簡單,過濾條件較爲固定

服務操作

服務開啓、關閉、重啓、查看狀態

Mysql.server start/restart/stop/status

Mysql.server 文件安裝時在安裝目錄下可以找到

查看Mysql服務

ps -ef |grep mysql

連接

連接

安裝後,第一次連接不需要密碼,直接回車就進去了。

mysql -u root -p 輸入之後回車,再回車。設置密碼之後第一次回車之後輸入密碼即可。

進入指定庫:

mysql -u root -p dbname

退出

exitquit

幫助命令

進入命令行輸入help或者? + command即可查看對應語法。

舉例:

mysql> help select;

或者

mysql> ? select;

用戶管理

用戶

添加

命令格式:

CREATE USER 'username'@'host' IDENTIFIED BY 'password';

host一般爲%代替匹配任何字符

重命名

rename USER user to user1

刪除用戶

drop user user1

密碼

設置密碼

  1. 命令行設置

    mysqladmin -u root password "123456" 這個命令在mysql安裝目錄的bin目錄下,最好將這個目錄設置到環境變量path中

  2. 進入mysql設置

    use mysql; 說明使用那個數據庫

    root用戶:

    SET PASSWORD = PASSWORD('biscuit');

    指定用戶:

    SET PASSWORD FOR 'jeffrey'@'%' = PASSWORD('biscuit');

修改密碼

更新已有賬戶密碼:

UPDATE user SET Password = PASSWORD('bagel') WHERE Host = '%' AND User = 'francis';

權限

授權

命令格式:

GRANT ALL PRIVILEGES ON *.*(庫.表) TO 'backlion'(用戶)@'%'(地址,%爲匹配符) IDENTIFIED BY 'backlion123'(密碼) WITH GRANT OPTION; 括號裏面是說明,實際不寫括號

被授權用戶不能再授權,如果想,則需要在授權命令末尾加上 WITH GRANT OPTION

查看指定用戶權限

show grants for user1

撤銷權限

撤銷某個表的部分權限:

REVOKE all privilege(select,update,delete,insert) ON dbname.tablename FROM 'username'@'host';

撤銷所有權限:

revoke ALL PRIVILEGES on *.* from user1

重新載入授權表

FLUSH PRIVILEGES

數據庫操作

常用命令

查看數據庫狀態 mysql> status;
查看編碼 mysql> show variables like 'char%';
修改編碼 alter database db_name CHARACTER SET utf8;
顯示數據庫當前狀態 show status;
顯示線程表 show processlist;
查看mysql提供引擎 show engines;
看當前默認的存儲引擎 show variables like '%storage_engine%';
修改表引擎 alter table table_name engine=innodb;
查詢當前sql模式 SELECT @@sql_mode
殺死對應線程id KILL thread_id;

創建庫

create database dbname default character set utf8mb4 collate utf8_general_ci;

使用庫

use dbname;

修改庫

重命名:

rename database oldname to newname;

修改字符集:

alter database character set utf8mb4;

刪除庫

drop database IF EXISTS dbname;

查看庫

顯示所有庫:

show databases;

查看創建庫的sql語句:

show create database test;

列類型

查看官網的數據庫表列類型

創建表

CREATE TABLE  IF NOT EXISTS `person` (
  `number` int(11) DEFAULT NULL AUTO_INCREMENT COMMENT '機器ID',
  `name` varchar(255) DEFAULT NULL,
  `birthday` date DEFAULT NULL
	PRIMARY KEY (number),--------主鍵
	UNIQUE KEY  `unique_fname_lname` (`fisrtname`,`lastname`),
	KEY `fname_lname_age`  (`firstname`,`lastname`,`age`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

創建臨時表:

CREATE TEMPORARY TABLE table_name();

舉例:

create temporary table student_copy(
  id int primary key,
  name varchar(20) 
)Engine=InnoDB default charset utf8;

臨時表只對當前連接有效。

修改表

修改表的引擎:

alter table tableName engine=innodb;

修改表的字符集:

alter table tableName convert to character set utf8mb4;

移動表到其他數據庫:

rename TABLE current_db.tbl_name TO other_db.tbl_name;

重命名錶:

rename table 原表名 to 新表名;

修改表字段:

增:

alter table table1 add transactor varchar(10) not Null;

刪:

alter table table_name drop column 字段名;

改:

alter table 表名稱 change 舊名稱 新名稱 字段類型 [是否允許非空]; #修改字段名

alter table 表名稱 modify 字段名 字段類型 [是否允許非空]; #修改字段其他屬性

刪除表

刪除指定表:

drop table table_name;

刪除數據庫中的所有表:

select concat('drop table ',table_name,';') from TABLES where table_schema='dbname';

查看錶

show tables;

顯示所有列信息:

desc tableName;

刪除表中的數據

delete from table1; 範圍刪除,之後插入id不會從1開始

truncate table table1; 清空表,索引從1開始

SELECT

語法

SELECT
    [ALL | DISTINCT | DISTINCTROW ]
      [HIGH_PRIORITY]
      [MAX_STATEMENT_TIME = N]
      [STRAIGHT_JOIN]
      [SQL_SMALL_RESULT] [SQL_BIG_RESULT] [SQL_BUFFER_RESULT]
      [SQL_CACHE | SQL_NO_CACHE] [SQL_CALC_FOUND_ROWS]
    select_expr [, select_expr ...]
    [FROM table_references
      [PARTITION partition_list]
    [WHERE where_condition]
    [GROUP BY {col_name | expr | position}
      [ASC | DESC], ... [WITH ROLLUP]]
    [HAVING where_condition]
    [ORDER BY {col_name | expr | position}
      [ASC | DESC], ...]
    [LIMIT {[offset,] row_count | row_count OFFSET offset}]
    [PROCEDURE procedure_name(argument_list)]
    [INTO OUTFILE 'file_name'
        [CHARACTER SET charset_name]
        export_options
      | INTO DUMPFILE 'file_name'
      | INTO var_name [, var_name]]
    [FOR UPDATE | LOCK IN SHARE MODE]]

單表查詢

舉例:

where:

select id, tag_name from test where id = 22

GROUP BY:

HAVING子句可以引用總計函數,而WHERE子句不能引用

SELECT user, MAX(salary) FROM users GROUP BY user HAVING MAX(salary)>10;

LIMIT分頁:

SELECT * FROM tbl LIMIT 5,10; # Retrieve rows 6-15; 從索引5開始找10個數據

INTO OUTFILE查詢結果寫入服務器文件:

SELECT a,b,a+b INTO OUTFILE '/tmp/result.text' 
FIELDS TERMINATED BY ',' 
OPTIONALLY ENCLOSED BY '"' 
LINES TERMINATED BY '\n'
FROM test_table;

UNION:將多個查詢結果放到一個結果集中

SELECT ...
UNION [ALL | DISTINCT]
SELECT ...
[UNION [ALL | DISTINCT]
SELECT ...]

ORDER BY排序:

ASC (升序,默認)

DESC (降序)

多表查詢

join

  • 內連接:inner join,笛卡爾積匹配;
  • 左連接:left join,右表匹配左表
  • 右連接:right join,左表匹配右表

舉例:

SELECT * from facts t1 LEFT JOIN oper_log t2 ON t1.id=t2.id;

一般不會三個不同連接一起使用

INSERT

語法

INSERT [LOW_PRIORITY | DELAYED | HIGH_PRIORITY] [IGNORE]
    [INTO] tbl_name
    [PARTITION (partition_name,...)]
    [(col_name,...)]
    {VALUES | VALUE} ({expr | DEFAULT},...),(...),...
    [ ON DUPLICATE KEY UPDATE
      col_name=expr
        [, col_name=expr] ... ]

Or:

INSERT [LOW_PRIORITY | DELAYED | HIGH_PRIORITY] [IGNORE]
    [INTO] tbl_name
    [PARTITION (partition_name,...)]
    SET col_name={expr | DEFAULT}, ...
    [ ON DUPLICATE KEY UPDATE
      col_name=expr
        [, col_name=expr] ... ]

Or:

INSERT [LOW_PRIORITY | HIGH_PRIORITY] [IGNORE]
    [INTO] tbl_name
    [PARTITION (partition_name,...)]
    [(col_name,...)]
    SELECT ...
    [ ON DUPLICATE KEY UPDATE
      col_name=expr
        [, col_name=expr] ... ]

舉例

批量插入

INSERT INTO oper_log(oper_name, oper_detail) VALUES("admin1", "insert data"),("admin2", "insert data");

插入時存在更新

這種情況必須存在主鍵或者唯一索引,否則直接插入

insert into record_detail (logid, detail) VALUES (2,'bob2'),(3,'bob3') on DUPLICATE KEY UPDATE detail = VALUES(detail);

或者:

1. replace into tbl_name(col_name, ...) values(...)
2. replace into tbl_name(col_name, ...) select ...
3. replace into tbl_name set col_name=value, ...

使用查詢結果插入

insert into tablename (id, col_name) select id, col_name from t_table where 1=1;

UPDATE

語法

Single-table syntax:

UPDATE [LOW_PRIORITY] [IGNORE] table_reference
    SET col_name1={expr1|DEFAULT} [, col_name2={expr2|DEFAULT}] ...
    [WHERE where_condition]
    [ORDER BY ...]
    [LIMIT row_count]

Multiple-table syntax:

UPDATE [LOW_PRIORITY] [IGNORE] table_references
    SET col_name1={expr1|DEFAULT} [, col_name2={expr2|DEFAULT}] ...
    [WHERE where_condition]

舉例

多表聯合更新:

UPDATE record_detail t1 LEFT JOIN oper_log t2 ON t1.logid=t2.id SET t1.detail = t2.oper_detail WHERE t2.oper_name = '用戶2';

一般不建議使用多表關聯更新

單表更新:

UPDATE record_detail SET detail = 'update data' WHERE id = 1;

DELETE

語法

Single-Table Syntax

DELETE [LOW_PRIORITY] [QUICK] [IGNORE] FROM tbl_name
    [PARTITION (partition_name,...)]
    [WHERE where_condition]
    [ORDER BY ...]
    [LIMIT row_count]
    
Multiple-Table Syntax

DELETE [LOW_PRIORITY] [QUICK] [IGNORE]
    tbl_name[.*] [, tbl_name[.*]] ...
    FROM table_references
    [WHERE where_condition]

Or:

DELETE [LOW_PRIORITY] [QUICK] [IGNORE]
    FROM tbl_name[.*] [, tbl_name[.*]] ...
    USING table_references
    [WHERE where_condition]

舉例

單表刪除

delete from record_detail WHERE id = 1;

多表刪除

delete t1, t2 from record_detail t1 LEFT JOIN oper_log t2 on t1.logid=t2.id WHERE t2.id = 6;

函數

類型轉換

SELECT CAST(logid as char) FROM record_detail;

SELECT CONVERT(logid, char) FROM record_detail;

可轉換的類型:

BINARY[(N)]

CHAR[(N)]

DATE

DATETIME

DECIMAL

SIGNED [INTEGER]

TIME

UNSIGNED [INTEGER]

數學運算

mysql> select abs(-8); ##絕對值
±--------+
| abs(-8) |
±--------+
| 8 |
±--------+

mysql>select ceiling(9.4); ##向上取整
±-------------+
| ceiling(9.4) |
±-------------+
| 10 |
±-------------+

mysql> select floor(3.4); ##向下取整
±-----------+
| floor(3.4) |
±-----------+
| 3 |
±-----------+

mysql> select rand(); ##返回0–1的隨機數
±-------------------+
| rand() |
±-------------------+
| 0.7959931481592293 |
±-------------------+

字符串函數

mysql> select char_length('length'); ##計算字符串長度
±----------------------+
| char_length(‘length’) |
±----------------------+
| 6 |
±----------------------+

mysql> select concat('aaa','bbb','ccc'); ##拼接字符串
±--------------------------+
| concat(‘aaa’,‘bbb’,‘ccc’) |
±--------------------------+
| aaabbbccc |
±--------------------------+

mysql> selectinsert('abcdefghijk', 2,4,'xxxxxxxx'); ##具體位置插入字符串替代幾個字符,也可作爲替換使用。說明:從第2個位置開始的4個字符刪除,用後面的字符串替換。
±--------------------------------------+
| insert(‘abcdefghijk’, 2,4,‘xxxxxxxx’) |
±--------------------------------------+
| axxxxxxxxfghijk |
±--------------------------------------+

mysql>select lower('ABCDEF'); ##大寫轉小寫 upper():小寫轉大寫
±----------------+
| lower(‘ABCDEF’) |
±----------------+
| abcdef |
±----------------+

mysql> select instr('abcdefgh', 'g'); ##查找第一個出現的位置
±-----------------------+
| instr(‘abcdefgh’, ‘g’) |
±-----------------------+
| 7 |
±-----------------------+

mysql> select substr('abcdefghi',3,2); ##獲取從某個位置開始長度爲n的字串
±------------------------+
| substr(‘abcdefghi’,3,2) |
±------------------------+
| cd |
±------------------------+

mysql> select replace('abcdefghijk','j','xx'); ##字符串替換
±--------------------------------+
| replace(‘abcdefghijk’,‘j’,‘xx’) |
±--------------------------------+
| abcdefghixxk |
±--------------------------------+

時間函數

時間獲取

mysql> select curdate(); ##當前日期
±-----------+
| curdate() |
±-----------+
| 2020-04-26 |
±-----------+

mysql> select now(); ##當前時間
±--------------------+
| now() |
±--------------------+
| 2020-04-26 09:14:12 |
±--------------------+

mysql> select year(NOW()); ##獲取當前時間的年,month,day,hour,minute,second
±------------+
| year(NOW()) |
±------------+
| 2020 |
±------------+

日期和天數轉換

SELECT TO_DAYS(NOW()); -- 737908
SELECT FROM_DAYS(737908); -- 2020-04-28

時間和秒數轉換

SELECT TIME_TO_SEC(NOW()); -- 56744
SELECT SEC_TO_TIME(56609); -- 15:43:29

時間拼湊

SELECT MAKETIME(2,3,5); -- 02:03:05
SELECT MAKEDATE(2021,300); -- 2021-10-27

日期計算

– HOUR,MINUTE,SECOND,WEEK,MONTH,YEAR
SELECT DATE_ADD(NOW(), INTERVAL 1 DAY); -- 加一天
SELECT DATE_SUB(NOW(), INTERVAL 1 QUARTER); -- 減三個月

時間差

SELECT DATEDIFF('2008-12-30','2008-12-29'); --1

SELECT TIMEDIFF('15:45:44','15:47:44'); -- 00:02:00

時區轉換

select convert_tz('2008-08-08 12:00:00', '+08:00', '+00:00'); -- 2008-08-08 04:00:00

聚合函數

函數 說明
count() 計算個數,count(字段):會忽略所有的null;count(*)與count(1)區別:1只查一列,二者不會忽略null列
sum() 求和
avg() 平均分
max() 最高分
min() 最低分

數據庫級別MD5加密

mysql>select md5('22222'); ##加密
±---------------------------------+
| md5(‘22222’) |
±---------------------------------+
| 3d2172418ce305c7d16d4b05597c6a59 |
±---------------------------------+

事務

原則

原子性(A)

一致性©

隔離性(I)

髒讀

事務A讀取了事務B更新的數據,然後B回滾操作,那麼A讀取到的數據是髒數據

幻讀

系統管理員A將數據庫中所有學生的成績從具體分數改爲ABCDE等級,但是系統管理員B就在這個時候插入了一條具體分數的記錄,當系統管理員A修改結束後發現還有一條記錄沒有改過來,就好像發生了幻覺一樣,這就叫幻讀。

不可重複讀

事務 A 多次讀取同一數據,事務 B 在事務A多次讀取的過程中,對數據作了更新並提交,導致事務A多次讀取同一數據時,結果 不一致。

總結

不可重複讀的和幻讀很容易混淆,不可重複讀側重於修改,幻讀側重於新增或刪除。

解決不可重複讀的問題只需鎖住滿足條件的行,解決幻讀需要鎖表

持久性(D)

#設置是否自動提交事務,默認自動提交
#關閉自動提交
set autocommit = 0;  

#開啓事務
start TRANSACTION

#操作
insert
insert 

#提交
COMMIT
#回滾
ROLLBACK
#開啓自動提交
set autocommit = 1; 

索引

快速獲取數據庫中的數據

分類

  • 主鍵索引(PRIMARY KEY)

    不可重複

  • 唯一索引(UNIQUE KEY)

    避免重複的列出現,唯一索引可以重複,多個列都可以標識爲唯一索引

  • 常規索引(KEY/INDEX)

    默認的,index和key設置

  • 全文索引(FullText)

    快速定位數據,myisam引擎下有效

操作

Syntax:
CREATE [UNIQUE|FULLTEXT|SPATIAL] INDEX index_name
    [index_type]
    ON tbl_name (index_col_name,...)
    [index_option]
    [algorithm_option | lock_option] ...

示例:

create index index_name on test(col_name);

說明:

1.只有當正在使用MyISAM, BDB或InnoDB表類型時,可以向BLOB(二進制流)或TEXT列中添加索引,也可以向有NULL值的列中添加索引

2.FULLTEXT索引只能對CHAR, VARCHAR和TEXT列編制索引,並且只能在MyISAM表中編制。

3.SPATIAL索引只能對空間列編制索引,並且只能在MyISAM表中編

alter table table_name Drop index index_name;

drop index index_name on table_name;

刪除主鍵索引:

alter table table_name drop primary key;

添加主鍵索引:

alter table table_name add primary key(id);

添加唯一索引:

alter table table_name add unique name_unique_index (col_name);

添加普通索引:

alter table table_name add index index_name (col_name);

禁用/激活非唯一索引:

alter table table_name disable | enable keys;

show index from table_name;

批量插入

-- 寫函數之前必須要寫的標誌,避免語句總有分號直接停止後續語句的執行
DELIMITER $$  
create FUNCTION mock_data()		-- 函數名
RETURNS INT			-- 返回值
BEGIN	-- 函數體
	-- 變量名
	DECLARE num int DEFAULT  1000000;
	declare i int default 0;
	-- 開啓循環
	while i < num do
		-- 執行的語句
		insert into oper_log(oper_name,oper_detail) values (CONCAT('用戶',i),CONCAT('{\"json1\":',i,'}'));
		set i = i+1;
	end while;
	
	return i;
END;

#執行函數
SELECT mock_data();

#刪除函數
DROP PROCEDURE mock_data;

索引使用原則

  • where 子句或者join子句中出現的列

分析SQL效率

explain

mysql> explain select * from facts;
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------+
| id | select_type | table | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------+
|  1 | SIMPLE      | facts | NULL       | ALL  | NULL          | NULL | NULL    | NULL |    1 |   100.00 | NULL  |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------+

結果顯示說明:
table:這是表的名字。
type:連接操作的類型。匹配行數,最好顯示const,all最差
possible_keys:可能可以利用的索引的名字
Key:MySQL實際使用的索引的名字
key_len:索引中被使用部分的長度,以字節計
rows:MySQL所認爲的它在找到正確的結果之前必須掃描的記錄數

分析慢查詢sql

show variables like '%slow_query_log%'; 查看慢查詢是否開啓和日誌保存路徑

配置

slow_query_log = 1
slow_query_log_file = /tmp/mysql_slow.log
#查詢閾值,大於這個值記錄到日誌
long_query_time = 10  

使用工具分析慢查詢日誌

mysqldumpslow -s r -t 10 /usr/local/mysql/data/slow.log

命令說明:

-s 自定義按那種排序方式輸出結果
c:總次數
t:總時間
l:鎖的時間
r:總行數
at,al,ar:平均數的意思
-t 指定取前幾條數據

備份

歸檔模式與非歸檔模式對比

歸檔模式 非歸檔模式
做熱備份,並且可以做增量備份,可以做部分恢復 非歸檔就是不保存舊事務日誌
只能做冷備份,並且恢復時只能做完全備份.最近一次完全備份到系統出錯期間的數據不能恢復.

冷熱備份

對比 冷備份 熱備份
指在數據庫關閉後,進行備份,適用於所有模式的數據庫 針對歸檔模式的數據庫,在數據庫仍舊處於工作狀態時進行備份

數據庫使用歸檔方式運行時纔可以進行災難性恢復

如果數據庫處於非歸檔模式,聯機日誌在切換時就會丟棄. 而在歸檔模式下,當發生日誌切換的時候,被切換的日誌會進行歸檔

導出數據庫

導出表結構

mysql的bin目錄找到mysqldump:

mysqldump -u 用戶名 -p 密碼 -d 數據庫名 > 數據庫名.sql

導出數據和表結構,包含存儲過程、函數

mysqldump -u 用戶名 -p 密碼 -R -d 數據庫名 > 數據庫名.sql

具體其他參數,可以使用 ./mysqldump --help 查看

導入數據庫

導入前需要確定數據庫是否存在。

如果數據庫名包含符號,使用反引號將庫名包裹起來。

命令行

mysql -u用戶名 -p密碼 數據庫名 < 數據庫名.sql

Mysql命令行:

use DbName;

source /home/abc/abc.sql; #這裏是sql文件的絕對路徑

動態備份

基於mysqldump通常就是:完整備份 + 二進制日誌 來進行恢復

https://www.cnblogs.com/xsuid/archive/2018/08/03/9416593.html

數據庫設計

三大範式

第一範式

每張表的每列都是不可再分的。列的原子性。

第二範式

前提 滿足第一範式

每一列都和主鍵相關(針對聯合主鍵而言)

即一個表只描述一件事情。

第三範式

前提 滿足第二範式

消除傳遞依賴

命名

  • 庫名(可以顯示項目信息),表名(顯示功能),字段(合理使用字段類型,字段命名可以查看功能,非負使用unsigned,範圍小使用tinyint),單條記錄最好不超過8K
  • myisam:建議使用國定長度的數據列代替可變長度。
  • 能用tinyint就不用integer
  • 如果需要使用小數嚴謹使用float,double,使用定點數decimal,decimal實際上是以字符串的形式存儲的(但是會佔用更多的存儲空間),所以更加精確,java中與之對應的數據類型爲BigDecimal
  • 對於金額直接使用bigint存儲
  • tinyint(2),對於整型來說小括號中的2不是指的存儲長度,而是指的零填充達到長度2

分表

單錶行數超過500萬行或者單表容量超過 2GB,才推薦進行分庫分表

分區

將數據庫的表分割成多個表,當然看到的還是一個表,只不過物理保存的時候是多個文件。使用分區的前提是表是獨立空間存儲的。

可以在建表時分區,也可以在之後分區。

舉例:

create table emp_date(
id int not null,
separated date not null default '9999-12-31'
)
#以某個字段分區
partition by range columns(separated) (
partiontion p0 values less than ('1990-01-01'),
partiontion p0 values less than ('2001-01-01'),
partiontion p0 values less than ('2018-01-01')
);

參考

數據切分

水平切分 垂直切分
定義:
按照一定規則切分單個表 根據功能模塊分類多個表
特點:
◆ 數據庫的拆分簡單明瞭,拆分規則明確; ◆ 應用程序模塊清晰明確,整合容易; ◆ 數據維護方便易行,容易定位; ◆ 表關聯基本能夠在數據庫端全部完成; ◆ 不會存在某些超大型數據量和高負載的表遇到瓶頸的問題; ◆ 應用程序端整體架構改動相對較少; ◆ 事務處理相對簡單; ◆ 只要切分規則能夠定義好,基本上較難遇到擴展性限制;
缺點:
◆ 部分表關聯無法在數據庫級別完成,需要在程序中完成; ◆ 對於訪問極其頻繁且數據量超大的表仍然存在性能平靜,不一定能滿足要求; ◆ 事務處理相對更爲複雜; ◆ 切分達到一定程度之後,擴展性會遇到限制; ◆ 過讀切分可能會帶來系統過渡複雜而難以維護。 ◆ 切分規則相對更爲複雜,很難抽象出一個能夠滿足整個數據庫的切分規則; ◆ 後期數據的維護難度有所增加,人爲手工定位數據更困難 ◆ 應用系統各模塊耦合度較高,可能會對後面數據的遷移拆分造成一定的困難。
整合方案:自行編寫中間代理層 使用開源框架: AmoebaForMySQL:只能是mysql協議連接與數據源 AmoebaForAladin:mysql協議連接,可以多種數據源 HiveDB:只支持水平切分,
切分和整個之後問題:
分佈式事務問題:可以在應用解決爲單一數據源 跨節點join問題:可由應用解決,通過查詢驅動 跨節點合併排序分頁問題:可由應用解決

注意:

實際設計時需要根據實際業務需求設計。

數據庫優化

有哪些優化方面
字段類型、分表存儲、事務處理、數據庫參數優化(最大連接、佔用內存等)、讀寫分離(主從複製)、增加緩存(redis, memcached等)、升級硬件設備(磁盤IO讀寫速度,CPU,內存,帶寬)

SQL優化

  1. GROUP BY NULL 禁止排序避免對結果排序的消耗

  2. ORDER BY 使用索引

  3. INSERT 插入多行使用values一次插入,不要多次插入

  4. INSERT DELAYED 多個連接同時插入時,使用延遲插入提高插入速度

  5. 如果只是查詢,設置配置mysql的low_priority_updates=1,降低寫的優先級

  6. 大量數據操作時分批操作,這樣不會導致一個線程佔用表太長時間

  7. 不要在where條件表達式寫計算表達式,儘量少使用函數對字段操作,這樣會導致不會使用索引。簡單判斷即可

  8. 對以下操作符才使用索引:
    <,<=,=,>,>=,BETWEEN,IN,以及某些時候的LIKE。
    不要寫==!=,<>==,用between或者> and < 代替

  9. 少用子查詢,使用連接(JOIN)來代替子查詢(Sub-Queries)

  10. where 條件中不要使用 or(導致全表掃描),使用聯合替代

    舉例:

    select id from t where num=10 or Name = 'admin'
    替換:
    select id from t where num = 10
    union all
    select id from t where Name = 'admin'
    
  11. in 和not in最好別用,容易導致全表掃描,一些情況下,可以使用exists替換in。
    使用exists先查詢主表,再與子查詢作對比;
    in先查詢子查詢,在和主表笛卡爾。
    如果子查詢記錄多,用exists;如果子查詢少,用in

  12. 最好不要使用like ’ ', 全表掃描

  13. 字段儘量設置爲not null

  14. or只有兩邊都是索引才使用索引

  15. 查詢時字段類型要正確,否則不使用索引

  16. 模糊查詢只有最前綴使用索引,即%在後面匹配

  17. 使用連接(JOIN)來代替子查詢(Sub-Queries)

JDBC

對數據庫使用統一接口

代碼實現步驟

  1. 註冊Driver

    Class.forName("com.mysql.jdbc.Driver");

  2. 連接數據庫

    //用戶與連接信息
    String  url = "jdbc:mysql://localhost:3306/dbname?useUnicode=true&characterEncoding=utf8&useSSL=true";
    String username = "root";
    String password = "123456"
    
    //連接獲取connection
    Connection connection = DriverManager.getConnect(url, username, password);
    
    //獲取執行對象
    Statement statement = connection.createStatement();
    
  3. 操作數據庫

    //sql 語句
    String sql = "SELECT * from test";
    
    //執行sql
    ResultSet resultSet = statement.executeQuery(sql);
    
    //訪問結果,具體方法查看對應類或者使用時.選擇對應函數
    resultSet.getObject("columnName");
    
  4. 關閉資源

    resultSet.close();
    statement.close();
    connection.close();
    

SQL注入

參數沒有處理導致注入sql,實現非法操作

'or 1=1'

PreparedStatement 對象防止sql注入

連接池

druid

阿里提供的數據庫連接池

C3P0

xml配置參數

DBCP

需要jar包

commons-dbcp-1.4

commons-pool-1.6

FAQ

mysql啓動出現錯誤

mysql.sock 文件丟失
或者
Manager of pid-file quit without updating file.[FAILED] 

方法:

/usr/local/bin/mysql_install_db

忘記密碼

方法一:
修改配置文件my.conf,添加skip-grant-tables
重啓mysql並登陸(無密碼)
修改mysql數據庫中root用戶密碼
update user set authentication_string=password('123456') where user='root';
刷新權限:
flush privileges;
退出,刪除配置文件中添加項
方法二:
不檢查權限方式啓動
mysql -u root -p --skip-grant-tables &(可加選項)
登陸修改密碼即可
update MySQL.user set password=PASSWORD('newpassword') where User='root';
flush privileges;

字段中存在引號

數據庫插入字段中包含單引號,只需要將單引號替換爲雙引號即可。

刪除表中重複字段,保留一個

DELETE from t_entity_terminal WHERE termid in(SELECT termid from (SELECT max(termid) as termid from t_entity_terminal GROUP BY machinesid HAVING COUNT(machinesid) > 1) as tmpresult);

需要建立臨時表,否則刪除不成功

數據庫表crash修復

1.關閉mysql服務
2.myisamchk -f -o tablename.MYI

或者

檢查
mysqlcheck -u root -p wordpress
備份
mysqldump -u root -p wordpress > wordpress.sql
修復
mysqlcheck -u root -p wordpress --auto-repair

更新不同字段爲不同值

UPDATE mytable 
SET myfield = CASE id 
WHEN 1 THEN 'value'
WHEN 2 THEN 'value'
WHEN 3 THEN 'value'
END
WHERE id IN (1,2,3)

查詢結果導入臨時表

CREATE TEMPORARY TABLE a_test as SELECT id  FROM t_log_terminalupgrade  GROUP BY machineid,planid HAVING COUNT(1) > 1 ;

批量修改表的引擎

#使用concat函數重組sql語句即可,
#table_name:表名
#table_schema:數據庫名

查看sql:
SELECT CONCAT(table_name,'  ', engine)
FROM information_schema.tables WHERE table_schema="testdb" AND ENGINE="MyISAM";
修改sql:
SELECT CONCAT('ALTER TABLE ',table_name,' ENGINE=InnoDB;') FROM information_schema.tables
WHERE table_schema="testdb" AND ENGINE="MyISAM";

查看哪些表被鎖定

show OPEN TABLES where In_use > 0;

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章