sql學習筆記(18)-----------數據庫建立過程

手動建立數據庫的步驟:
 
第一步:決定數據庫實例的SID
數據庫實例的SID用來將當前實例和之後可能建立的實例進行區分
% setenv ORACLE_SID mynewdb
 
 
第二步:創建數據庫管理員認證方法
 
 
第三步:建立初始化參數文件
實例(由內存結構SAG和後臺進程組成)啓動過程當中要讀取初始化參數文件。獲得初始化參數文件的一個好辦法是改動一個已有的初始化參數文件。爲了簡化操做,將初始化參數文件放在Oracle默認的位置上。這種話。當數據庫啓動時,就沒有必要再指定pfile參數了。因爲Oracle會本身主動尋找在默認位置的初始化參數文件。
Platform                  Default Name                  Default Location
UNIX                    init$ORACLE_SID.ora          $ORACLE_HOME/dbs
Windows                  init$ORACLE_SID.ora          $ORACLE_HOME/database
假設一個數據庫的名字是mynewdb,如下就是該數據庫的初始化文件:
# Cache and I/O
DB_BLOCK_SIZE=4096
DB_CACHE_SIZE=20971520
 
# Cursors and Library Cache
CURSOR_SHARING=SIMILAR
OPEN_CURSORS=300
 
# Diagnostics and Statistics
BACKGROUND_DUMP_DEST=/vobs/oracle/admin/mynewdb/bdump
CORE_DUMP_DEST=/vobs/oracle/admin/mynewdb/cdump
TIMED_STATISTICS=TRUE
USER_DUMP_DEST=/vobs/oracle/admin/mynewdb/udump
 
# Control File Configuration
CONTROL_FILES=("/vobs/oracle/oradata/mynewdb/control01.ctl",
"/vobs/oracle/oradata/mynewdb/control02.ctl",
"/vobs/oracle/oradata/mynewdb/control03.ctl")
 
# Archive
LOG_ARCHIVE_DEST_1='LOCATION=/vobs/oracle/oradata/mynewdb/archive'
LOG_ARCHIVE_FORMAT=%t_%s.dbf
LOG_ARCHIVE_START=TRUE
 
# Shared Server
# Uncomment and use first DISPATCHES parameter below when your listener is
# configured for SSL
# (listener.ora and sqlnet.ora)
# DISPATCHERS = "(PROTOCOL=TCPS)(SER=MODOSE)",
# "(PROTOCOL=TCPS)(PRE=oracle.aurora.server.SGiopServer)"
DISPATCHERS="(PROTOCOL=TCP)(SER=MODOSE)",
"(PROTOCOL=TCP)(PRE=oracle.aurora.server.SGiopServer)",
(PROTOCOL=TCP)
# Miscellaneous
COMPATIBLE=9.2.0
DB_NAME=mynewdb
# Distributed, Replication and Snapshot
DB_DOMAIN=us.oracle.com
REMOTE_LOGIN_PASSWORDFILE=EXCLUSIVE
# Network Registration
INSTANCE_NAME=mynewdb
 
# Pools
JAVA_POOL_SIZE=31457280
LARGE_POOL_SIZE=1048576
SHARED_POOL_SIZE=52428800
# Processes and Sessions
PROCESSES=150
# Redo Log and Recovery
FAST_START_MTTR_TARGET=300
# Resource Manager
RESOURCE_MANAGER_PLAN=SYSTEM_PLAN
# Sort, Hash Joins, Bitmap Indexes
SORT_AREA_SIZE=524288
# Automatic Undo Management
UNDO_MANAGEMENT=AUTO
UNDO_TABLESPACE=undotbs
 
第四步:鏈接到實例
$ SQLPLUS /nolog
CONNECT SYS/password AS SYSDBA
 
第五步:啓動實例
不mount數據庫。只啓動實例。一般,不過在建立和維護數據庫的時候才這樣作。
STARTUP NOMOUNT
此時,數據庫並不存在。僅僅有SGA和後臺進程被建立。

 
 
第六步:調用create database語句
CREATE DATABASE mynewdb
USER SYS IDENTIFIED BY pz6r58
USER SYSTEM IDENTIFIED BY y1tz5p
LOGFILE GROUP 1 ('/vobs/oracle/oradata/mynewdb/redo01.log') SIZE 100M,
GROUP 2 ('/vobs/oracle/oradata/mynewdb/redo02.log') SIZE 100M,
GROUP 3 ('/vobs/oracle/oradata/mynewdb/redo03.log') SIZE 100M
MAXLOGFILES 5
MAXLOGMEMBERS 5
MAXLOGHISTORY 1
MAXDATAFILES 100
MAXINSTANCES 1
CHARACTER SET US7ASCII
NATIONAL CHARACTER SET AL16UTF16
DATAFILE '/vobs/oracle/oradata/mynewdb/system01.dbf' SIZE 325M REUSE
EXTENT MANAGEMENT LOCAL
DEFAULT TEMPORARY TABLESPACE tempts1
DATAFILE '/vobs/oracle/oradata/mynewdb/temp01.dbf'
SIZE 20M REUSE
UNDO TABLESPACE undotbs
DATAFILE '/vobs/oracle/oradata/mynewdb/undotbs01.dbf'
SIZE 200M REUSE AUTOEXTEND ON NEXT 5120K MAXSIZE UNLIMITED;
數據庫建立以後,數據庫名稱是mynewdb,它的全局數據庫名是mynewdb.us.oracle.com。控制文件經過初始化參數CONTROL_FILES來建立。SYS用戶的password是pz6r58,SYSTEM用戶的password是y1tz5p。這兩個子句在Oracle9i中是可選。但是假設設定了不論什麼一個password,那麼兩個password都必須設定。

該數據庫有三個在線重作日誌組。經過LOGFILE子句來指定,MAXLOGFILES, MAXLOGMEMBERS, and MAXLOGHISTORY都是對日誌文件的限制。php

MAXDATAFILES指定了數據庫可以打開的數據文件的最大數量,該數量會影響到控制文件的大小。在建立數據庫的過程當中所設定的參數,有些會受到其它因素的影響。前端

比方,設定了MAXDATAFILES以後,Oracle在控制文件裏要分配空間存放數據文件的文件名稱。即便數據庫僅僅有一個數據文件。然而,因爲控制文件自己也有大小的限制(跟操做系統有關)。很是有可能不能把所有CREATE DATABASE的參數都設置爲他們理論上的最大值。mysql

MAXINSTANCES 指定了僅僅有一個實例能夠 mount 和打開數據庫。 US7ASCII 字符集被指定爲數據庫保存數據使用的字符集。系統表空間由 /vobs/oracle/oradata/mynewdb/system01.dbf 組成,假設該文件已經存在。將會被重寫。系統表空間是本地化管理的表空間。
DEFAULT_TEMPORARY_TABLESPACE子句建立並命名了一個默認的暫時表空間。UNDO_TABLESPACE子句建立並命名了一個撤銷表空間。用來存儲撤銷記錄,前提是在初始化參數文件裏把UNDO_MANAGEMENT設定爲AUTO。因爲ARCHIVELOG子句在CREATE DATABASE語句中沒有調用,所以重作日誌文件並不會被歸檔。這是數據庫建立過程的一般作法,ALTER DATABASE語句可以用來切換到ARCHIVELOG模式。

初始化文件裏的LOG_ARCHIVE_DEST_1,LOG_ARCHIVE_FORMAT, and LOG_ARCHIVE_START三個參數與歸檔有關。sql

 
 
 
 
第七步:建立額外的表空間
爲了使數據局效率更高。需要建立額外的表空間和文件
CONNECT SYS/password AS SYSDBA
-- create a user tablespace to be assigned as the default tablespace for users
CREATE TABLESPACE users LOGGING
DATAFILE '/vobs/oracle/oradata/mynewdb/users01.dbf'
SIZE 25M REUSE AUTOEXTEND ON NEXT 1280K MAXSIZE UNLIMITED
EXTENT MANAGEMENT LOCAL;
-- create a tablespace for indexes, separate from user tablespace
CREATE TABLESPACE indx LOGGING
DATAFILE '/vobs/oracle/oradata/mynewdb/indx01.dbf'
SIZE 25M REUSE AUTOEXTEND ON NEXT 1280K MAXSIZE UNLIMITED
EXTENT MANAGEMENT LOCAL;
EXIT
 
第八步:建立server參數文件
Oracle建議建立一個server參數文件。做爲維護初始化參數的動態方式。如下的腳本依據初始化參數文件建立了一個server初始化參數文件,並把該初始化參數文件放在默認位置。實例關閉後又一次啓動時,就會使用默認位置的server初始化參數文件。
CONNECT SYS/password AS SYSDBA
-- create the server parameter file
CREATE SPFILE='/vobs/oracle/dbs/spfilemynewdb.ora' FROM
PFILE='/vobs/oracle/admin/mynewdb/scripts/init.ora';
SHUTDOWN
-- this time you will start up using the server parameter file
CONNECT SYS/password AS SYSDBA
STARTUP
EXIT
 
 
 數據庫的優化
 

mysql表複製                                                                              數據庫

複製表結構+複製表數據後端

1
2
mysql> create table t3 like t1;
mysql> insert into t3 select * from t1;

mysql索引                                                                                 bash

1
2
3
4
5
6
7
8
9
10
11
12
ALTER TABLE 用來建立普通索引、 UNIQUE 索引或 PRIMARY KEY 索引
ALTER TABLE table_name ADD INDEX index_name (column_list)
ALTER TABLE table_name ADD UNIQUE (column_list)
ALTER TABLE table_name ADDPRIMARY KEY (column_list)
Create Index
CREATE INDEX index_name ON table_name (column_list)
CREATE UNIQUE INDEX index_name ON table_name (column_list)
drop index
DROP INDEX index_name ON talbe_name
alter table table drop
ALTER TABLE table_name DROP INDEX index_name
ALTER TABLE table_name DROP PRIMARY KEY

mysql視圖                                                                                session

建立視圖
oracle

1
2
mysql> create view v_t1 as select * from t1 where id>4 and id<11;
Query OK, 0 rows affected (0.00 sec)

view視圖的幫助信息
socket

1
2
3
4
mysql> ? view
ALTER VIEW
CREATE VIEW
DROP VIEW

查看視圖

1
mysql> show tables;

刪除視圖v_t1

1
mysql> drop view v_t1;

mysql內置函數                                                                           

字符串函數

1
2
3
4
5
6
7
8
9
10
CONCAT (string2 [,… ]) //鏈接字串
LCASE (string2 ) //轉換成小寫
UCASE (string2 ) //轉換成大寫
LENGTH (string ) //string長度
LTRIM (string2 ) //去除前端空格
RTRIM (string2 ) //去除後端空格
REPEAT (string2 , count ) //反覆 count
REPLACE (str ,search_str ,replace_str ) //在str中用replace_str替換search_str
SUBSTRING (str , position [,length ]) //從str的position開始,取length個字符
SPACE ( count ) //生成 count 個空格

數學函數

1
2
3
4
5
6
7
BIN (decimal_number ) //十進制轉二進制
CEILING (number2 ) //向上取整
FLOOR (number2 ) //向下取整
MAX (num1 ,num2) //取最大值
MIN (num1,num2) //取最小值
SQRT(number2) //開平方
RAND() //返回0-1內的隨機值

日期函數

1
2
3
4
5
6
7
8
CURDATE() //返回當前日期
CURTIME() //返回當前時間
NOW() //返回當前的日期時間
UNIX_TIMESTAMP( date ) //返回當前 date 的UNIX日間戳
FROM_UNIXTIME() //返回UNIX時間戳的日期值
WEEK( date ) //返回日期 date 爲一年中的第幾周
YEAR ( date ) //返回日期 date 的年份
DATEDIFF(expr,expr2) //返回起始時間expr和結束時間expr2間天數

mysql預處理語句                                                                        

設置stmt1預處理,傳遞一個數據做爲一個where推斷條件

1
mysql> prepare stmt1 from 'select * from t1 where id>?

';

設置一個變量
mysql> set @i=1;
運行stmt1預處理
mysql> execute stmt1 using @i;
設置@i爲5
mysql> set @i=5;
再次去運行stmt1
mysql> execute stmt1 using @i;
怎樣刪除預處理stmt1
mysql> drop prepare stmt1;

mysql事務處理                                                                         

1
2
3
4
5
6
7
8
9
10
11
12
13
14
--關閉本身主動提交功能
mysql> set autocommit=0;
--從表t1中刪除了一條記錄
mysql> delete from t1 where id=11;
--此時作一個p1還原點:
mysql> savepoint p1;
--再次從表t1中刪除一條記錄:
mysql> delete from t1 where id=10;
--再次作一個p2還原點:
mysql> savepoint p2;
--此時恢復到p1還原點。固然後面的p2這些還原點本身主動會失效: 
mysql> rollback to p1;
--退回到最原始的還原點:
mysql> rollback ;


mysql存儲                                                                                

建立一個存儲p1()

1
2
3
4
5
6
7
8
9
10
mysql> \d //
mysql> create procedure p1()
-> begin
-> set @i=0;
-> while @i<10 do
-> select @i;
-> set @i=@i+1;
-> end while ;
-> end;
-> //

運行存儲p1()

1
2
3
4
5
6
mysql> \d ;
mysql> call p1();
--查看procedure p1()的status信息
mysql> show procedure status\G
--查看procedure p1()的詳細信息:
mysql> show create procedure p1\G

mysql觸發器                                                                              

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
改動delimiter爲 //
mysql> \d //
建立一個名字爲tg1的觸發器,當向t1表中插入數據時。就向t2表中插入一條數據
   
mysql> create trigger tg1 before insert on t1 for each ro
>begin
>insert into t2( id ) values(new. id ); 
>end //
--準備兩個空表t1和t2
mysql> select * from t1;
mysql> select * from t2;
--向t1表中插入多條數據:
mysql> insert into t1 values(1),(2),(3),(4);
  
怎樣製做刪除表t1後t2表中的記錄也會跟着刪除呢
mysql>\d //
mysql> create trigger tg2 beforedelete on t1 for each row 
>begin delete from t2 where id =old. id ;
>end //
mysql>\d ;
怎樣製做更改表t1後t2表中的記錄跟着個性呢
mysql>\d //
mysql> create trigger tg3 beforeupdate on t1 for each row 
>begin update t2 set id =new. id where id =old. id
>end //
mysql>\d ;
查看觸發器
mysql> show triggers;

重排auto_increment值                                                             

1
2
3
4
5
6
7
8
9
10
11
MYSQL數據庫本身主動增加的ID怎樣恢復,清空表的時候。

不能用

  
delete from tablename;
而是要用:
  
truncatetable tablename;
這樣auto_increment 就恢復成1了
  
或者清空內容後直接用ALTER命令改動表:
  
altertable tablename auto_increment =1;

利用GROUP BY的WITH ROLLUP                                               

1
2
3
4
5
6
7
8
9
10
11
12
mysql> select * from demo; 
+-------+-------+ 
| cname | pname | 
+-------+-------+ 
| bj | hd | 
| bj | xc | 
| bj | hd | 
| sh | dh | 
| sh | rg | 
| sh | dh | 
+-------+-------+ 
9 rows in set (0.00 sec)


對demo表依照cname、pname列分組對pname列進行聚合計算例如如下

1
2
3
4
5
6
7
8
9
10
11
mysql> select cname,pname,count(pname) from demo group by 
cname,pname;
+-------+-------+--------------+
| cname | pname | count(pname) |
+-------+-------+--------------+
| bj | hd | 3 |
| bj | xc | 2 |
| sh | dh | 3 |
| sh | rg | 1 |
+-------+-------+--------------+
4 rows in set (0.00 sec)

相同使用with rollupkeyword後,統計出不少其它的信息。例如如下。

注意:with rollup不可以和ordery by同一時候使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
ysql> select cname,pname,count(pname) from demo group by cname,pname 
with rollup;
+-------+-------+--------------+
| cname | pname | count(pname) |
+-------+-------+--------------+
| bj | hd | 3 |
| bj | xc | 2 |
| bj | NULL | 5 |
| sh | dh | 3 |
| sh | rg | 1 |
| sh | NULL | 4 |
| NULL | NULL | 9 |
+-------+-------+--------------+
7 rows in set (0.00 sec)

使用外鍵需要注意的問題                                                               

建立外鍵的方式

1
2
mysql>create table temp( id int, name char(20), foreign key( id
references outTable( id ) on delete cascade on update cascade)。

注意:Innodb類型的表支持外鍵,myisam類型的表。儘管建立外鍵可以成功,但是不起做用,主要緣由是不支持外鍵。

優化SQL語句的通常步驟                                                                

經過show status命令瞭解各類SQL的運行頻率

1
mysql> show [session|global]status;

當中:session(默認)表示當前鏈接,global表示自數據庫啓動至今

1
2
3
4
mysql>show status;
mysql>show global status;
mysql>show status like ‘Com_%';
mysql>show global status like ‘Com_%';

參數說明:

Com_XXX表示每個XXX語句運行的次數如:
Com_select 運行select操做的次數,一次查詢僅僅累計加1
Com_update 運行update操做的次數
Com_insert 運行insert操做的次數,對批量插入僅僅算一次。


Com_delete 運行delete操做的次數
僅僅針對於InnoDB存儲引擎的:

InnoDB_rows_read 運行select操做的次數
InnoDB_rows_updated 運行update操做的次數
InnoDB_rows_inserted 運行insert操做的次數
InnoDB_rows_deleted 運行delete操做的次數
其它:

connections 鏈接mysql的數量
Uptime server已經工做的秒數
Slow_queries:慢查詢的次數
定位運行效率較低的SQL語句

1
2
explain select * from table where id=1000;
desc select * from table where id=1000;

經過EXPLAIN分析較低效SQL的運行計劃

1
2
3
4
5
6
7
8
9
10
11
12
13
mysql> explain select count(*) from stu where name like "a%" \G 
*************************** 1. row *************************** 
id : 1 
select_type: SIMPLE 
table: stu 
type : range 
possible_keys: name,ind_stu_name 
key: name 
key_len: 50 
ref: NULL 
rows: 8 
Extra: Using where; Using index 
1 row in set (0.00 sec)

每一列的簡單解釋


id: 1
select_type: SIMPLE 表示select的類型。常見的取值有SIMPLE()簡單表。即不使用錶鏈接或者子查詢)、PRIMARY(主查詢,即外層的查詢)、UNION(UNION中的第二個或者後面的查詢語句)、SUBQUERY(子查詢中的第一個SESECT)等
table: stu  輸出結果集的表
type: range 表示表的鏈接類型。性能有好到差:system(表僅一行)、const(僅僅一行匹配)、eq_ref(對於前面的每一行使用主鍵和惟一)、ref(同eq_ref,但沒有使用主鍵和惟一)、ref_or_null(同前面對null查詢)、index_merge(索引合併優化)、unique_subquery(主鍵子查詢)、index_subquery(非主鍵子查詢)、range(表單中的範圍查詢)、index(都經過查詢索引來獲得數據)、all(經過全表掃描獲得的數據)
possible_keys: name,ind_stu_name 表查詢時可能使用的索引。
key: name  表示實際使用的索引。
key_len: 50 索引字段的長度
ref: NULL
rows: 8 掃描行的數量
Extra: Using where; Using index 運行狀況的說明和描寫敘述

索引問題                                                                                     

MyISAM存儲引擎的表的數據和索引是本身主動分開存儲的,分別是獨一的一個文件;InnoDB存儲引擎的表的數據和索引是存儲在同一個表空間裏面,但可以有多個文件組成。MySQL眼下不支持函數索引,但是能對列的前面某一部分進行索引,好比name字段,可以僅僅取name的前4個字符進行索引。這個特性可以大大縮小索引文件的大小,用戶在設計表結構的時候也可以對文本列依據此特性進行靈活設計。

1
mysql>create index ind_company2_name on company2(name(4));

--當中company表名ind_company2_name索引名
MySQL怎樣使用索引
一、使用索引

(1)對於建立的多列索引。僅僅要查詢的條件中用到最左邊的列。索引通常就會被使用。例如如下建立一個複合索引。

1
mysql>create index ind_sales2_com_mon on sales2(company_id,moneys);

而後按company_id進行查詢。發現使用到了複合索引

1
mysql>explain select * from sales2 where company_id=2006\G

使用如下的查詢就沒有使用到複合索引。

1
mysql>explain select * from sales2 where moneys=1\G

(2) 使用like的查詢,後面假設是常量並且僅僅有%號不在第一個字符。索引纔可能會被使用。例如如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
mysql> explain select * from company2 where name like "%3" \G 
*************************** 1. row *************************** 
id : 1 
select_type: SIMPLE 
table: company2 
type : ALL 
possible_keys: NULL 
key: NULL 
key_len: NULL 
ref: NULL 
rows: 1000 
Extra: Using where 
1 row in set (0.00 sec)


例如如下這個使用到了索引。而如下樣例可使用索引,差異就在於「%」的位置不一樣,上面的樣例是吧「%」放在了第一位,而如下的樣例則沒有

1
2
3
4
5
6
7
8
9
10
11
12
13
mysql> explain select * from company2 where name like "3%" \G 
*************************** 1. row *************************** 
id : 1 
select_type: SIMPLE 
table: company2 
type : range 
possible_keys: ind_company2_name 
key: ind_company2_name 
key_len: 11 
ref: NULL 
rows: 103 
Extra: Using where 
1 row in set (0.00 sec)


(3)假設對大的文本進行搜索,使用全文索引而不使用like「%...%」.

(4)假設列名是索引。使用column_name is null將使用索引。例如如下

1
2
3
4
5
6
7
8
9
10
11
12
13
mysql> explain select * from company2 where name is null\G 
*************************** 1. row *************************** 
id : 1 
select_type: SIMPLE 
table: company2 
type : ref 
possible_keys: ind_company2_name 
key: ind_company2_name 
key_len: 11 
ref: const 
rows: 1 
Extra: Using where 
1 row in set (0.00 sec)


存在索引但不使用索引
(1)假設MySQL預計使用索引比全表掃描更慢,則不使用索引。好比假設列key_part1均勻分佈在1到100之間,查詢時使用索引就不是很是好

1
mysql> select * from table_name where key_part1>1 and key_part<90;

(2)假設使用MEMORY/HEAP表並且where條件中不使用「=」進行索引列。那麼不會用到索引。Heap表僅僅有在「=」的條件下會使用索引。

(3)用or切割開的條件。假設or前的條件中的列有索引,然後面的列中沒有索引,那麼涉及的索引都不會被用到。

1
2
3
4
5
6
7
mysql>show index from sales\G 
*************************** 1. row *************************** 
…… 
key_name: ind_sales_year 
seq_in_index:1 
Column_name: year 
……


從上面可以發現僅僅有year列上面有索引。

來看例如如下的運行計劃。

1
2
3
4
5
6
7
8
9
10
11
12
13
mysql> explain select * from sales where year=2001 or country=‘China'\G 
*************************** 1. row *************************** 
id : 1 
select_type: SIMPLE 
table: sales 
type : ALL 
possible_keys: ind_sales_year 
key: NULL 
key_len: NULL 
ref: NULL 
rows: 12 
Extra: Using where 
1 row in set (0.00 sec)


(4)假設不是索引列的第一部分,例如如下樣例:可見儘管在money上面建有複合索引,但是由於money不是索引的第一列,那麼在查詢中這個索引也不會被MySQL採用。

1
2
3
4
5
6
7
8
9
10
11
12
13
mysql> explain select * from sales2 where moneys=1 \G 
*************************** 1. row *************************** 
id : 1 
select_type: SIMPLE 
table: sales2 
type : ALL 
possible_keys: NULL 
key: NULL 
key_len: NULL 
ref: NULL 
rows: 1000 
Extra: Using where 
1 row in set (0.00 sec)

(5)假設like是以%開始。可見儘管在name上面建有索引。但是由於where 條件中like的值的「%」在第一位了,那麼MySQL也會採用這個索引。

(6)假設列類型是字符串,但在查詢時把一個數值型常量賦值給了一個字符型的列名name。那麼儘管在name列上有索引,但是也沒實用到。

1
2
3
4
5
6
7
8
9
10
11
12
13
mysql> explain select * from company2 where name name=294\G 
*************************** 1. row *************************** 
id : 1 
select_type: SIMPLE 
table: company2 
type : ALL 
possible_keys: ind_company2_name 
key: NULL 
key_len: NULL 
ref: NULL 
rows: 1000 
Extra: Using where 
1 row in set (0.00 sec)

而如下的sql語句就可以正確使用索引。

1
2
3
4
5
6
7
8
9
10
11
12
13
mysql> explain select * from company2 where name name=‘294'\G 
*************************** 1. row *************************** 
id : 1 
select_type: SIMPLE 
table: company2 
type : ref 
possible_keys: ind_company2_name 
key: ind_company2_name 
key_len: 23 
ref: const 
rows: 1 
Extra: Using where 
1 row in set (0.00 sec)

查看索引使用狀況
假設索引正在工做。Handler_read_key的值將很是高,這個值表明了一個行被索引值讀的次數。

Handler_read_rnd_next的值高則意味着查詢執行低效。並且應該創建索引補救。

1
2
3
4
5
6
7
8
9
10
11
12
mysql> show status like 'Handler_read%'
+-----------------------+-------+ 
| Variable_name | Value | 
+-----------------------+-------+ 
| Handler_read_first | 0 | 
| Handler_read_key | 5 | 
| Handler_read_next | 0 | 
| Handler_read_prev | 0 | 
| Handler_read_rnd | 0 | 
| Handler_read_rnd_next | 2055 | 
+-----------------------+-------+ 
6 rows in set (0.00 sec)

兩個簡單有用的優化方法                                                                

分析表的語法例如如下:(檢查一個或多個表是否有錯誤)

1
2
3
4
5
6
7
8
9
mysql> CHECK TABLE tbl_name[,tbl_name] …[option] …option = 
{ QUICK | FAST | MEDIUM| EXTENDED | CHANGED} 
mysql> check table sales; 
+--------------+-------+----------+----------+ 
| Table | Op | Msg_type | Msg_text | 
+--------------+-------+----------+----------+ 
| sakila.sales | check | status | OK | 
+--------------+-------+----------+----------+ 
1 row in set (0.01 sec)

優化表的語法格式:

OPTIMIZE [LOCAL | NO_WRITE_TO_BINLOG] TABLE tbl_name [,tbl_name]
假設已經刪除了表的一大部分,或者假設已經對含有可變長度行的表進行了很是多的修改。則需要作按期優化。

這個命令可以將表中的空間碎片進行合併,但是此命令僅僅對MyISAM、BDB和InnoDB表起做用。

?
1
2
3
4
5
6
7
mysql> optimize table sales; 
+--------------+----------+----------+----------+ 
| Table | Op | Msg_type | Msg_text | 
+--------------+----------+----------+----------+ 
| sakila.sales | optimize | status | OK | 
+--------------+----------+----------+----------+ 
1 row in set (0.05 sec)

常用SQL的優化                                                                           

大批量插入數據
當用load命令導入數據的時候。適當設置可以提升導入的速度。

對於MyISAM存儲引擎的表,可以經過下面方式高速的導入大量的數據。

ALTER TABLE tbl_name DISABLE KEYS
loading the data
ALTER TABLE tbl_name ENABLE KEYS
DISABLE KEYS 和ENABLE KEYS 用來打開或關閉MyISAM表非惟一索引的更新,可以提快速度,注意:對InnoDB表無效。


--沒有使用打開或關閉MyISAM表非惟一索引:

1
2
3
mysql> load data infile ‘ /home/mysql/film_test .txt'into table film_test2; 
Query OK,529056 rows affected (1 min 55.12 sec) 
Records:529056 Deleted:0 Skipped:0 Warnings:0

--使用打開或關閉MyISAM表非惟一索引:

1
2
3
4
5
6
7
mysql> alter table film_test2 disable keys; 
Query OK,0 rows affected (0.0 sec) 
mysql> load data infile ‘ /home/mysql/film_test .txt'into table film_test2; 
Query OK,529056 rows affected (6.34 sec) 
Records:529056 Deleted:0 Skipped:0 Warnings:0 
mysql> alter table film_test2 enable keys; 
Query OK,0 rows affected (12.25 sec)

--以上對MyISAM表的數據導入,但對於InnoDB表並不能提升導入數據的效率

(1)針對於InnoDB類型表數據導入的優化

因爲InnoDB表的依照主鍵順序保存的,因此將導入的數據主鍵的順序排列,可以有效地提升導入數據的效率。


--使用test3.txt文本是按表film_test4主鍵存儲順序保存的

1
2
mysql> load data infile ‘ /home/mysql/film_test3 .txt'into table film_test4; 
Query OK, 1587168 rows affected (22.92 sec)

Records:1587168 Deleted:0 Skipped:0 Warnings:0
--使用test3.txt沒有不論什麼順序的文本(效率慢了1.12倍)

1
2
3
mysql> load data infile ‘ /home/mysql/film_test4 .txt'into table film_test4; 
Query OK, 1587168 rows affected (31.16 sec) 
Records:1587168 Deleted:0 Skipped:0 Warnings:0

(2)關閉惟一性效驗可以提升導入效率

在導入數據前先運行set unique_checks=0,關閉惟一性效驗,在導入結束後運行set unique_checks=1,恢復惟一性效驗,可以提升導入效率。


--當unique_checks=1時

1
2
3
mysql> load data infile ‘ /home/mysql/film_test3 .txt'into table film_test4; 
Query OK,1587168 rows affected (22.92 sec) 
Records:1587168 Deleted:0 Skipped:0 Warnings:0

--當unique_checks=0時

1
2
3
mysql> load data infile ‘ /home/mysql/film_test3 .txt'into table film_test4; 
Query OK,1587168 rows affected (19.92 sec) 
Records:1587168 Deleted:0 Skipped:0 Warnings:0

(3)關閉本身主動提交可以提升導入效率

在導入數據前先運行set autocommit=0。關閉本身主動提交事務。在導入結束後運行set autocommit=1,恢復本身主動提交,可以提升導入效率。


--當autocommit=1時

1
2
3
mysql> load data infile ‘ /home/mysql/film_test3 .txt'into table film_test4; 
Query OK,1587168 rows affected (22.92 sec) 
Records:1587168 Deleted:0 Skipped:0 Warnings:0

--當autocommit=0時

1
2
3
mysql> load data infile ‘ /home/mysql/film_test3 .txt'into table film_test4; 
Query OK,1587168 rows affected (20.87 sec) 
Records:1587168 Deleted:0 Skipped:0 Warnings:0

優化insert語句
儘可能使用多個值表的insert語句,這樣可以大大縮短客戶與數據庫的鏈接、關閉等損耗。

可以使用insert delayed(當即運行)語句獲得更高的效率。

將索引文件和數據文件分別存放不一樣的磁盤上。

可以添加bulk_insert_buffer_size 變量值的方法來提快速度。但是僅僅對MyISAM表使用當從一個文件裏裝載一個表時,使用LOAD DATA INFILE。這個一般比使用很是多insert語句要快20倍。

優化group by語句
假設查詢包括group by但用戶想要避免排序結果的損耗,則可以使用使用order by null來禁止排序:

例如如下沒有使用order by null來禁止排序

1
2
3
4
5
6
7
8
9
10
11
12
13
mysql> explain select id , sum (moneys) from sales2 group by id \G 
*************************** 1. row *************************** 
id : 1 
select_type: SIMPLE 
table: sales2 
type : ALL 
possible_keys: NULL 
key: NULL 
key_len: NULL 
ref: NULL 
rows: 1000 
Extra: Using temporary;Using filesort 
1 row in set (0.00 sec)

例如如下使用order by null的效果:

1
2
3
4
5
6
7
8
9
10
11
12
13
mysql> explain select id , sum (moneys) from sales2 group by id order by null\G 
*************************** 1. row *************************** 
id : 1 
select_type: SIMPLE 
table: sales2 
type : ALL 
possible_keys: NULL 
key: NULL 
key_len: NULL 
ref: NULL 
rows: 1000 
Extra: Using temporary 
1 row in set (0.00 sec)

優化嵌套查詢
如下是採用嵌套查詢的效果(可以使用更有效的連接查詢(Join)替代)。

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
mysql> explain select * from sales2 where company_id not in ( select id 
from company2)\G 
*************************** 1. row *************************** 
id : 1 
select_type: SIMPLE 
table: sales2 
type : ALL 
possible_keys: NULL 
key: NULL 
key_len: NULL 
ref: NULL 
rows: 1000 
Extra: Using where 
1 row in set (0.00 sec)
*************************** 2. row *************************** 
id : 2 
select_type: SIMPLE 
table: company2 
type : index_subquery 
possible_keys: ind_company2_id 
key: ind_company2_id 
key_len: 5 
ref: func 
rows: 2 
Extra: Using index 
1 row in set (0.00 sec)

如下是使用更有效的連接查詢(Join)

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
mysql> explain select * from sales2 left join company2 on 
sales2.company_id = company2. id where sales2.company_id is null\G 
*************************** 1. row ***************************
id : 1 
select_type: SIMPLE 
table: sales2 
type : ALL 
possible_keys: ind_sales2_companyid_moneys 
key: ind_sales2_companyid_moneys 
key_len: 5 
ref: count 
rows: 1 
Extra: Using where 
1 row in set (0.00 sec) 
*************************** 2. row *************************** 
id : 2 
select_type: SIMPLE 
table: company2 
type : index_subquery 
possible_keys: ind_company2_id 
key: ind_company2_id 
key_len: 5 
ref: func 
rows: 1 
Extra: 
1 row in set (0.00 sec)

從運行計劃中可以明顯看出查詢掃描的記錄範圍和使用索引的狀況都有了很是大的改善。鏈接(JOIN)子因此更有效率一些,是因爲MySQL不需要再內存中建立暫時表來完畢這個邏輯上的需要兩個步驟的查詢工做。

數據庫優化                                                                                  

優化表的類型
在MySQL中,可以使用函數PROCEDUREANALYSE()對當前應用的表進行分析,改函數可以對數據表中列的數據類型提出優化建議,用戶可以依據應用的實際狀況酌情考慮是否實施優化。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
mysql> select * from duck_cust procedure analyse()\G 
*************************** 1. row *************************** 
Field_name: sakila.duch_cust.cust_num 
Min_value: 1 
Max_value: 6 
Min_length: 1 
Max_length: 1 
Empties_or_zeros: 0 
Nulls: 0 
Avg_value_or_avg_length: 3.5000 
Std: 1.7078 
Optimal_fieldtype: ENUM(‘1 ',‘2' ,‘3 ',‘4' ) NOT NULL 
*************************** 2. row *************************** 
……


大存儲量解決
1.分庫分表

2.分區

主要目的:

1.下降表的記錄數

2.減少對操做系統的負擔壓力

中間表
中間表的產生:
1.view 視圖
2.又一次生成一個新表

Mysqlserver優化                                                                        

myisam讀鎖定
1.

lock table t1 read
2.開啓還有一個mysql鏈接終端,接着去嘗試:

select * from t1
3.再insert、update和delete t1這張表。你會發現所有的數據都停留在終端上沒有真正的去操做

4.讀鎖定對咱們在作備份大量數據時很實用.

mysqldump -uroot -p123 test >test.sql
myisam寫鎖定
1.

lock table t1 write
2.打開還有一個mysql終端,嘗試去select、insert、update和delete這張表t1,你會發現都不能操做,都會停留在終端上。僅僅有等第一個終端操做完成,第二個終端才幹真正運行.

3.可見表的寫鎖定比讀鎖定更嚴格

4.普通狀況下咱們很是少去顯式的去對錶進行read 和write鎖定的,myisam會本身主動進行鎖定的.

Mysqlserver優化                                                                       

二進制日誌
1.log-bin=mysql-bin

查看bin-log日誌:

mysql> show binary logs;
查看最後一個bin-log日誌:

mysql> show master status;
慢查詢日誌
開戶和設置慢查詢時間:

vi /etc/my.cnf
log_slow_queries=slow.log
long_query_time=5
慢查詢次數:

mysql> show global status like "%quer%"
socket問題
mysql socket沒法登陸

1. 有時登陸mysql時提示不能用socket登陸,此時可以換成tcp方式去登陸,但是可以測試時可以這樣用。但是必須要在php去用以前把這個事情攻克了.

1
2
3
4
5
6
[root@localhost mysql] # mysql -uroot -pwei --protocol tcp -hlocalhost
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 34
Server version: 5.0.77-log Source distribution
Type 'help;' or '\h' for help. Type '\c' to clear the buffer.
mysql>

這樣就可以登陸,這樣就不用mysql.sock來登陸。而mysql.sock是啓動mysqld服務時產生的

rootpassword丟失

rootpassword丟失破解

1
2
3
4
5
6
7
8
9
10
11
1.service mysqld stop
2. mysqld_safe --skip-grant-tables --user=mysql & 
//跳過受權表mysql.user和mysql.db這些表
3. mysql -uroot
4. set password=password("wei"); 
//用這一條語句結果報錯,就是因爲加了--skip-grant-tables
4. mysql>update user set password=password("wei") where user='root' 
and host='localhost';
5. mysql> set password for root@localhost=password("wei");
6. mysql> set password=password("wei"); 
//和第五步同樣,均可能成功改動password
相關文章
相關標籤/搜索