Maven增強
ts-manage 聚合工程嘉抓,小組的高級灵巧、中級程序員他來搭建聚合工程斩萌,包括聚合工程下的子項目许师。
ts-manage-pojo User.pojo,照貓畫虎寫其它模塊
ts-manage-mapper
ts-manage-service
ts-manage-controller/web
Maven增強
項目間關系:依賴公荧、繼承带射、聚合
- 依賴,調用jar時,maven會自動去找這個jar依賴的相關的其它的jar包稚矿。
- 繼承庸诱,jar管理,所有子項目中共有jar包晤揣,在此聲明桥爽,版本升級就非常的方便。
- 聚合昧识,在pom.xml中有一組module钠四,管理多個子項目,一鍵編譯跪楞。
測試(工作量非常大)和運維(部署)
2017年美國博士DevOpts開發(fā)運維一體化
Maven+GitHub版本控制+Jenkins
自動測試 JUnit @Test缀去,會自動產生一個測試報告
自動運維 自動從GitHub下載新的代碼,自動的編譯甸祭,自動打包缕碎,自動部署到tomcat下,自動啟動
ecshop網上開源商城代碼池户,小型電商咏雌。
mysql增強
在傳統(tǒng)企業(yè)中由DBA數據庫管理員凡怎,寫SQL,查詢性能調優(yōu)赊抖。
但是讓大家只是了解统倒?隨著硬件和互聯(lián)網,大數據的發(fā)展氛雪。例如:nosql 不僅僅是sql
關系型數據庫:Oracle房匆,SqlServer,MySQL
軟肋报亩,表的數據的關聯(lián)關系非常的密切浴鸿,多表聯(lián)查,隨著數據的增長捆昏,查詢越來越慢赚楚。
數據量有一定限制!
- Oracle單表可以支持到多少條數據骗卜?上億
- MySQL 1000萬
- nosql,最低億級數據以上左胞,mongodb,hbase
MySQL舊的方式在新的形勢下被淘汰:
1)視圖
2)存儲過程寇仓,函數
3)觸發(fā)器
舊的傳統(tǒng)的企業(yè),舊的系統(tǒng)還在使用這些舊的技術
我們面試時烤宙,會被問遍烦。
練習下面兩個視圖:============================================
CREATE VIEW v_goods238 AS
SELECT * FROM t_goods WHERE category_id=238
CREATE VIEW v_cat_goods AS
SELECT c.name,g.item_type,g.title FROM t_goods_category c
LEFT JOIN t_goods g
ON c.id=g.category_id
mysql增強,大型系統(tǒng)
1躺枕、【廢除】視圖服猪,本質就是一個查詢語句,作用把復雜SQL封裝起來拐云,調用中直接訪問視圖名稱即可罢猪。這樣調用者就非常方便。很難SQL就是DBA叉瘩,系統(tǒng)分析師膳帕。
2、【廢除】存儲過程薇缅,本質腳本語言(弱)危彩。性能高(在數據庫上直接執(zhí)行,它的服務器性能是所有服務器中最強)數據庫遷移oracle,mysql
3泳桦、【廢除】函數汤徽,本質自定義函數,豐富業(yè)務算法(個性)灸撰。
數據庫遷移oracle,mysql
4谒府、【廢除】觸發(fā)器拼坎,本質類似攔截器。也很死板狱掂。
數據庫遷移oracle,mysql
5演痒、索引,復合索引趋惨,最左前綴特性本質鸟顺,就是提高查詢效率
什么時候創(chuàng)建索引?用戶抱怨時器虾。
什么字段上創(chuàng)建索引讯嫂?where,order
主鍵有索引嗎?主鍵天生就有索引U咨场E费俊!葛圃!
1 數據庫編程(了解)
數據庫中可以編寫并保存一段程序千扔,做數據運算
- 視圖 View
- 存儲過程 Procudure
- 函數 Function
- 觸發(fā)器 Trigger
mysql 數據庫編程能力較弱,很多功能無法實現
2 變量
2.1 用戶會話變量
一個客戶端與服務器連接期間的變量
set @v1 = 123;
select @v1;
2.2 局部變量
? begin ... end; 是一對大括號库正,局部變量只能在 begin 到 end 之間使用曲楚,end結束后,變量消失
? 使用 declare 關鍵字來定義局部變量
? delimiter ; 結束符改成;
? delimiter // 結束符改成//
? 創(chuàng)建復雜的存儲過程中間會用到;結束符褥符,如果幾個;放在一起龙誊,MySQL只會識別第一個,以后的不會識別喷楣,這樣會及其不完整
begin
declare v2 int default 123;
select v2;
select @v1;
end//
(上面無法執(zhí)行趟大,只是參考)
3. 視圖
3.1 簡單視圖
? 視圖的本質就是一個查詢語句
select * from t_goods where category_id=238
create view v_goods238 as
select * from t_goods
where category_id=238;
select * from v_goods238;
DELIMITER $$ /*設定一個標識符,標識結束$$*/
USE `tedu_store`$$ /*打開指定數據庫tedu_store*/
DROP VIEW IF EXISTS `v_goods238`$$ /*如果此視圖已經存在铣焊,就刪除*/
create algorithm = undefined definer = `root`@`localhost` sql security
definer VIEW `v_goods238` as
select
`t_goods`.`id` AS `id`,
`t_goods`.`category_id` AS `category_id`,
`t_goods`.`item_type` AS `item_type`,
`t_goods`.`title` AS `title`,
`t_goods`.`sell_point` AS `sell_point`,
`t_goods`.`price` AS `price`,
`t_goods`.`num` AS `num`,
`t_goods`.`barcode` AS `barcode`,
`t_goods`.`image` AS `image`,
`t_goods`.`status` AS `status`,
`t_goods`.`priority` AS `priority`,
`t_goods`.`created_time` AS `created_time`,
`t_goods`.`modified_time` AS `modified_time`,
`t_goods`.`created_user` AS `created_user`,
`t_goods`.`modified_user` AS `modified_user`
FROM `t_goods`
WHERE (`t_goods`.`category_id` = 238)$$
DELIMITER ;
select * from v_goods238;
3.2 多級關聯(lián)視圖
create view v_cat_goods as
select
c.name,
g.item_type,
g.title
from
t_goods_category c
left join
t_goods g
on
c.id = g.category_id;
select * from v_cat_goods;
視圖在大型項目中被廢除Q沸唷!4纸亍惋耙!
視圖過程是把查詢所有的記錄都查詢回來,然后再過濾數據熊昌,過濾掉非238.
如果這張表中有一千萬數據绽榛。數據量大時無法優(yōu)化。
Java程序可以嗎婿屹?mybatis它直接處理灭美,返回結果數據。結果就比視圖快昂利。
4. 存儲過程
存儲過程是存儲在數據庫服務器中的一段過程代碼
優(yōu)點:
Jsp-java-database(proc)
存儲過程離數據庫最近届腐,所以它執(zhí)行代碼是效率最高的铁坎。
Client(brower)-WebServer(tomcat)-DatabaseServer(mysql)
WebServer和DatabaseServer,在企業(yè)中犁苏,WebServer一般服務器即可硬萍,但是DatabaseServer是所有服務器中最好的。甚至大型項目围详,小型機朴乖。Unix+Oracle。
? 廢除:
? 1) 寫數據庫代碼(存儲過程-單獨學習語法助赞,無法斷點买羞,system.out沒有輸出,幾乎無法調試雹食。DBA)畜普,寫java代碼(人員眾多,好調試)群叶。后期維護吃挑。不好維護。Java好維護街立。
? 2) 存儲過程不好寫儒鹿,質量不好控制。
4.1 定義存儲過程
-- 修改結束符
delimiter //
-- 創(chuàng)建存儲過程p1
create procedure p1()
begin -- 大括號開始
-- 定義局部變量v2
declare v2 int default 123;
select v2; -- 顯示v2變量的值
end// -- 大括號結束
4.2 調用存儲過程
call p1()//
4.3 查看存儲過程
show procedure status where db='db1'
查看指定庫中的存過程
show create procedure p1
4.4 刪除存儲過程
drop procedure if exists p1//
4.5 存儲過程的參數
三種參數:
- in 輸入參數
- out 輸出參數
- inout 既能輸入又能輸出
存儲過程參數測試
-- 向學生表和聯(lián)系方式表同時插入數據
-- 1) 插入學生數據
-- 2) 得到新插入的自增主鍵值
-- 3) 插入聯(lián)系方式表
傳統(tǒng)方式:
1. 頁面填寫兩張表的數據几晤,學生名稱,學生的電話植阴,存在兩個表中
2. 學生表自增主鍵
3. 聯(lián)系表中和學生表的關聯(lián)(一對一)
CREATE TABLE `t_student` (
`stu_id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(20) DEFAULT NULL,
PRIMARY KEY (`stu_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
CREATE TABLE `t_tel` (
`stu_id` int(11) NOT NULL,
`tel` varchar(30) DEFAULT NULL,
PRIMARY KEY (`stu_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
DELIMITER //
create procedure p_student_tel
(in name varchar(20),
in tel varchar(20), out id int)
begin
declare v int;-- 定義臨時變量用來存自增主鍵值
-- 插入學生數據
insert into t_student(name) values(name);
-- 獲得新生成的自增主鍵值存到v
set v = last_insert_id();
-- 插入聯(lián)系方式數據
insert into t_tel(stu_id,tel) values(v, tel);
-- 自增主鍵值存到輸出參數id
set id=v;
end//
-- 調用
CALL p_student_tel('劉強東',13010100808,@id);
-- 調用
CALL p_student_tel('劉強東',13010100808,@id);
select * from t_student;
select * from t_tel;
select @stu_id;
5 流程控制
5.1 if
if 條件 then
代碼
end if
if 條件 then
代碼1
else
代碼2
end if
5.2 case
case
when 條件1 then ...
when 條件2 then ...
else ...
end case
case 變量或表達式
when 值1 then ...
when 值2 then ...
else
end case
分支判斷測試
delimiter //
drop procedure if exists p1//
create procedure p1(in v int)
begin
if v=1 then
select 'v的值是1';
end if;
case v
when 2 then select 'v的值是2';
when 3 then select 'v的值是3';
else select 'v的值不是2,3';
end case;
end//
call p1(1) //
call p1(2) //
call p1(3) //
call p1(4) //
5.3 while
while 條件 do
代碼
end while
5.4 loop
-- lp: 循環(huán)命名蟹瘾,可以起任意的名字
lp: loop
...
if 條件 then
leave lp; -- 指定離開哪個循環(huán)
end if;
...
end loop;
5.5 repeat
repeat
代碼
until 條件 end repeat;
循環(huán)測試
-- 新建 tb1 表
use db1 //
drop table if exists tb1 //
create table tb1(
id int primary key auto_increment,
num int
)engine=innodb charset=utf8 //
delimiter //
drop procedure if exists p2//
create procedure p2(in n int)
begin
declare i int default 0;
-- while
while i<n do -- i的值從0遞增到n-1
insert into tb1(num) values(i+1);
set i=i+1;
end while;
-- loop
set i=0;
lp: loop
insert into tb1(num) values(i+1);
set i=i+1;
if i=n then -- i等于n時退出loop循環(huán)
leave lp;
end if;
end loop;
-- repeat
set i=0;
repeat
insert into tb1(num) values(i+1);
set i=i+1;
until i=n end repeat; -- i等于n時退出repeat循環(huán)
end//
call p2(10) //
select * from tb1 //
6. 函數
- 函數有返回值
- 調用存儲過程用call,調用函數直接調
函數為什么不讓用掠手?
分布式憾朴?又放在Java端
Zookeeper集群管理者,當一臺服務的配置更新喷鸽,zk會自動把配置改變信息更新到其它所有的機器上众雷。
5.1 創(chuàng)建函數
create function fn()
returns varchar(100)
begin
執(zhí)行代碼運算產生計算結果
return 計算結果;
end//
5.1.1求平方的函數 fn_pow
DELIMITER //
drop function if exists fn_pow //
create function fn_pow(n int)
returns int -- 函數返回什么類型的數據
begin
set r = n*n;
return r; -- 向調用位置返回計算結果
end //
select fn_pow(5) //
select *, fn_pow(num) from tb1 //
6.2 查看函數
show function status;
show function status where db='tedu_store';
show create function fn_pow;
6.2 刪除函數
drop function if exists fn_pow //
7 觸發(fā)器
對表中的數據操作時,可以觸發(fā)一段代碼執(zhí)行
三個數據操作:
- insert
- update
- delete
兩個觸發(fā)時間:
- before
- after
一張表中最多可以有6個觸發(fā)器
- before insert
- after insert
- before update
- after update
- before delete
- after delete
兩個隱含對象
-
new
? 新的數據行
? insert的new:要插入的新行
? update的new:修改后的新行
? delete的new:沒有 -
old
? 舊的數據行
? insert的old:沒有
? update的old:修改前的舊數據
? delete的old:被刪除的舊數據
訪問新行或舊行數據:
? new.id
? new.name
? old.age
? old.tel
7.1 創(chuàng)建觸發(fā)器
操作商品表insert,before,new
create trigger 名 觸發(fā)時間 on 表
for each row
begin
代碼
end;
用觸發(fā)器自動更新updated字段
-- 學生表添加 updated字段
alter table t_student
add created datetime //
-- 添加觸發(fā)器做祝,插入數據時自動填入時間
-- before insert
DELIMITER //
CREATE TRIGGER tr_b_i
BEFORE INSERT ON t_student FOR EACH ROW
BEGIN
SET new.created=NOW();
END //
insert into t_student(name) values('tony') //
select * from t_student //
-- 添加觸發(fā)器砾省,修改數據時自動修改時間
alter table t_student
add updated datetime //
DELIMITER //
CREATE TRIGGER tr_b_u
BEFORE UPDATE ON t_student FOR EACH ROW
BEGIN
SET new.updated = NOW();
END //
UPDATE t_student SET NAME='tina' WHERE stu_id=2
select * from t_student //
-- 級聯(lián)刪除。刪除主表信息時利用觸發(fā)器刪除子表信息
-- before delete
delimiter //
create trigger tr_b_d
before delete on t_student for each row
begin
delete from t_tel where stu_id=old.stu_id;
END //
select * from t_student;
select * from t_tel;
delete from t_student where name='a';
7.2 查看觸發(fā)器
進入系統(tǒng)庫 information_schema
use information_schema //
查詢 triggers 表中觸發(fā)器信息
select * from triggers
7.3 刪除觸發(fā)器
drop trigger 觸發(fā)器名
級聯(lián)刪除
刪除主表的數據時混槐。要把子表的數據刪除编兄。
8 數據庫的備份、恢復
8.1 備份方式:
1) 冷備份(按月)
2)熱備份
? a. 定時任務 Job (按周声登,日(凌晨2點)狠鸳,小時)揣苏、
? b. 實時備份(主從復制,實時同步)
查看數據安裝路徑
select @@basedir AS basePath FROM DUAL;
C:\Program Files\MySQL Server 5.5\bin>
使用 mysqldump 命令備份數據庫
使用 mysql 命令恢復數據庫
8.2 備份
退出 mysql件舵,在系統(tǒng)命令行執(zhí)行:
下面命令是一行代碼卸察,不能折行
mysqldump -uroot -p
--default-character-set=utf8 //表中存的是什么編碼
hr>d:\hr.sql //庫>文件
數據庫名
8.3 恢復
再次恢復:
1)在數據庫中新建一個庫
? create database jtdb2 charset utf8;
- 在系統(tǒng)命令行執(zhí)行恢復命令
? 下面命令是一行代碼,不能折行
mysql -uroot -p
--default-character-set=utf8
jtdb2:\jtds.sql
9. 索引
9.1 存儲過程產生大量數據
1) 創(chuàng)建一個內存表 tm, engine=memory
2) 創(chuàng)建一個磁盤表 td
3) 在存儲過程中铅祸,循環(huán) 20000 次向內存表插入隨機字符串
4) 把 20000 條數據坑质,一批存磁盤表
5)清空內存表
-- 內存表
drop table if exists tm;
create table tm(
c varchar(20)
) engine=memory chaset=utf8;
-- 磁盤表
drop table if exists td;
create table td(
id int primary key auto_increment,
c varchar(20)
) engine=innodb charset=utf8;
-- 存儲過程
drop procedure if exists gen_data;
delimiter //
create procedure gen_data(in n int)
begin
declare i int default 0;
while i<n do
insert into tm values (uuid());
set i=i+1;
end while;
insert into td(c) select c from tm;
delete from tm;
end //
call gen_data(1000)
DROP PROCEDURE IF EXISTS test_insert;
DELIMITER //
CREATE PROCEDURE test_insert(cnt INT)
BEGIN
DECLARE i INT DEFAULT 0;
START TRANSACTION;
WHILE i<cnt
DO
INSERT INTO td(c) VALUES(UUID());
SET i=i+1;
END WHILE;
COMMIT;
END //
call test_insert(1000);
9.2 索引優(yōu)化
索引其本質是創(chuàng)建了一張索引表,現有表的拷貝
(索引需要代價个少,插入數據要重新排序)
只拷貝現有表的指定索引字段洪乍。重要是做了一件事情:
排序
為什么它要排序呢? 為什么排序后就快了呢夜焦?
不創(chuàng)建索引壳澳,查詢時,全表遍歷茫经。
折半算法
用索引提高數據查找效率
-- 沒有索引巷波,花3.5秒查詢
select * from td where c='ab' //
-- 對c字段創(chuàng)建索引,花1分40秒左右
create index td_c_index on td(c) //
-- 有索引查詢花費 0.00 秒
select * from td where c='ab' //
9.3 MySQL 驗證索引的使用-最左前綴特性
復合索引
通過 EXPLAIN 關鍵字可以判斷查詢 SQL 語句是否使用索引
EXPLAIN select * from td where c='ab'
Possible_keys如果有值就代表使用了哪個索引卸伞,如果null就代表查詢沒有使用索引抹镊,全表遍歷。
SELECT * FROM tb1
WHERE user_id=100;
SELECT * FROM tb1
WHERE order_id=300;
SELECT * FROM tb1
WHERE user_id=100 AND order_id=300;
SELECT * FROM tb1
WHERE order_id=300 AND user_id=100 ;
沒使用索引
EXPLAIN
SELECT * FROM t_goods
WHERE title LIKE '%皮面%'
使用索引
EXPLAIN
SELECT * FROM t_goods
WHERE title LIKE '皮面%'
沒有使用索引
EXPLAIN
SELECT * FROM t_goods
WHERE title LIKE '%皮面'
EXPLAIN select * from tb_cart where user_id=1 and item_id=1
EXPLAIN select * from tb_cart where user_id=1
EXPLAIN SELECT * FROM tb_cart WHERE item_id=1
查看SQL的執(zhí)行計劃荤傲,可以看出第一句垮耳、第二句SQL使用了索引,第三句 SQL未使用索引遂黍。很好的證明了索引左側前綴特性终佛。
注意:
1)下面的語句違反了左側前綴的特性,為何仍然可以使用索引呢雾家?因為MYSQL對SQL語句有優(yōu)化铃彰,它會重新組合where條件。
EXPLAIN SELECT * FROM tb_cart WHERE item_id=1 AND user_id=1
2)沒有where條件的查詢是不會使用索引的芯咧。
10. 作業(yè)
商品表 tb_item
select * from tb_item;
有什么品牌
select distinct brand from tb_item;
最貴商品的品牌牙捉、名稱、價格
select brand,title,price
from tb_item
order by price desc
limit 1;
分頁查看商品
select id,brand,title,price
from tb_item
order by price desc
-- limit 0,10;
-- limit 10,10;
-- limit 20,10;
limit 30,10;
商品名和商品描述
select
title,item_desc
from
tb_item i
join
tb_item_desc
on
i.id = d.item_id
limit 1;
商品分類表 tb_item_cat
select * from tb_item_cat;
select *
from
tb_item_cat
where
name like '%電腦%'
or
name like '%筆記本%'
or
name like '%手機%';
查詢所有的頂層分類
select * from tb_item_cat
where
is_parent=1
and
parent_id is null;
查詢 161 下的二層分類
select * from
tb_item_cat
where
parent_id=161
order by sort_order;
查詢 162 下的三層分類
select * from tb_item_cat
where
parent_id=162
order by
sort_order;
用戶表
select * from tb_user;
訂單表
select * from tb_order;
用戶 id 是14的訂單
select * from tb_order where user_id=14;
訂單編號是 20161001490698615071
查詢這個訂單的所有商品
select * from tb_order_item
where order_id=20161001490698615071;
訂單編號是 20161001490698615071
? 查詢每種類別的商品數量
select cid,count(*) from tb_item group by cid
查詢 類別 163 的商品
select id,title,price from tb_item where cid=163;
? 查詢商品價格不大于100的商品名稱列表
select id,title,price from tb_item where price<100;
? 查詢品牌是聯(lián)想,且價格在40000以上的商品名稱和價格
select id,title,price from tb_item where brand='聯(lián)想' and price>40000;
? 查詢品牌是三木,或價格在10以上的商品名稱和價格
select id,brand,title,price from tb_item where brand='三木' or price<50;
? 查詢品牌是三木敬飒、廣博邪铲、齊心的商品名稱和價格
select id,brand,title,price from tb_item where brand in('三木','廣博','齊心');
? 查詢品牌不是聯(lián)想、戴爾的商品名稱和價格
select id,brand,title,price from tb_item where brand not in('聯(lián)想','戴爾');
? 查找品牌是聯(lián)想且價格大于10000的電腦名稱
select id,brand,title,price from tb_item where brand='聯(lián)想' and price>10000;
? 查詢聯(lián)想或戴爾的電腦名稱列表
select id,brand,title,price from tb_item where brand='聯(lián)想' or brand='戴爾';
? 查詢聯(lián)想驶拱、戴爾霜浴、三木的商品名稱列表
select id.brand,title,price from tb_item where brand in('聯(lián)想','戴爾','三木');
? 查詢不是戴爾的電腦名稱列表
select id,brand,title,price from tb_item where brand not in('戴爾');
? 查詢所有是記事本的商品品牌、名稱和價格
select id,brand,title,price from tb_item where title like '%記事本%';
? 查詢品牌是末尾字符是'力'的商品的品牌蓝纲、名稱和價格
select id,brand,title,price from tb_item where brand like '%力';
? 名稱中有聯(lián)想字樣的商品名稱
select id,brand,title,price from tb_item where title like '%聯(lián)想%';
? 查詢賣點含有'爆款'電腦名稱
select id,brand,title,price from tb_item where cell_point like '%爆款%';
? 查詢開頭字母是A的電腦名稱
select id,brand,price from tb_item where title like 'A%';
? 將地址表中的城市阴孟、地區(qū)晌纫、詳細地址組合到一起,
select concat(receiver_city, receiver_district,receiver_address) addr from tb_address;
? 獲取訂單編號為 20161001490698615071 中的每種商品的標題、單價永丝、數量锹漱、總價
select title,price,num,total_fee from tb_order_item where order_id='20161001490698615071';
? 統(tǒng)計商品表中各個品牌的商品數量
select brand,count(*) from tb_item group by brand
? 統(tǒng)計商品表中各個品牌的商品數量,并且按照數量從少到多排序
select brand,count(*) c from tb_item group by brand order by c;
? 統(tǒng)計商品表中各個品牌的商品數量,去除品牌為NULL的行,并且按照數量從少到多排序
select brand,count(*) c from tb_item where brand is not null group by brand order by c;
? 查詢不同品牌中最貴的商品價格
select id,title,brand,price from tb_item where(brand,price) in(select brand,max(price) m from tb_item where brand is not null group by brand);
? 將不同品牌中最貴的商品按照價格降序排序
select id,title,brand,price from tb_item where (brand,price)in(select brand,max(price) m from tb_item where brand is not null group by brand) order by price desc;
? 找出不同品牌中最貴的商品的前三名
select id,title,brand,price from tb_item where (brand,price)in(select brand,max(price) m from tb_item where brand is not null group by brand) order by price desc
limit 3;
? 查詢訂購了10000028商品的客戶姓名和聯(lián)系方式(三層子查詢)
? 首先查詢訂單表,根據10000028這個商品編號找到有該商品的訂單編號
? 然后查詢訂單表,根據上面得到的訂單編號找到訂購此訂單的用戶編號
? 最后查詢用戶表,根據第二部中查到的用戶編號,找到對應的用戶名和聯(lián)系方式
select id,username,phone,email from tb_user where id in (select user_id from tb_order where (select order_id from td_order_item where item_id=10000028))
select
distinct
from
td_user u
join
tb_order o
on
u.id=o.user_id
join
tb_order_item i
on
o.order_id=i.order_id
where
item_id=10000028