知識點

PHP

引用 &

驗證方法:

- var_dump(memory_get_usage());

- xdebug_debug_zval('變量名稱'); //需裝xdebug擴展
輸出示例:
p1:(refcount=1,is_ref=0)=class Person={.....}
//refcount: 指向該內存空間的變量個數
//is_ref: 是否有引用, 1-是,0-否
  1. 變量
普通傳值:$b = $a;
變量獨有的cow機制(copy on write),當賦值變量修改時纔會拷貝所需內存

引用傳值:$b = &$a;
兩個變量使用同一個內存區域

  1. 對象
$q = new OneObecjt();
$p = $q;
//對象本身就是引用傳遞

常量及數據類型

  1. 單引號和雙引號
- 單引號只能解析單引號和反斜線本身,無法解析變量
- 單引號效率比較高

  1. 三大數據類型(標量、複合、特殊)
標量:
- 浮點類型不能運用到比較運算中;

- 布爾類型,false的七種情況:
0, 0.0(浮點型),''(空字符串), '0', false, array(), NULL

- 數組類型,超全局數組:
$CLOBALS, $_GET, $_POST, $_REQUEST, $_SESSIONI, $_COOKIE, $_SERVIER, $_FILES, $_ENV

$_SERVER['SERVER_ADDR'] //服務器地址
$_SERVER['REMOTE_ADDR'] //客戶端地址,再找下其他信息


- NULL 三種情況:
直接賦值爲NULL, 未定義的變量,unset銷燬的變量

運算符

- 錯誤運算符: @ ,在一個PHP表達式之前,該表達式可能產生的任何錯誤信息都被忽略掉。
- 運算符優先級:

    遞增/遞減 > ! > 算術運算符 > 大小比較 > 相等比較 > 位運算符(^) > 位運算符(|) > 邏輯與 > 邏輯或 > 三目 > 賦值 > and > xor > or

    括號使用可增加代碼的可讀性。
- 比較運算符 : == 和 === 的區別
- 遞增、遞減:
    不影響布爾值
    遞減null值沒有效果
    遞減null值爲1
    在前則爲先運算符後返回,反之就先返回後運算
- 邏輯運算符: 
    短路作用
    ||和&& 同 or和and 的優先級不同


流程控制

- php遍歷數組的三種方式:
    ①使用for循環
    ②使用foreach循環
    ③使用while、list()、each()組合循環
    
    區別:
    for只能遍歷索引數組
    foreach以及組合循環可以遍歷關聯和索引數組
    組合循環不會進行reset()操作
    foreach會對數組進行reset()操作

- if 和 elseif
    使用elseif,總把優先範圍小的條件放在前面處理
    
- switch case
    switch後面的控制表達式的數據類型只能是整形,浮點類型, 字符串
    continue在switch中的作用相當於break
    跳出switch外的循環,可以使用continue 2
    

自定義以及內部函數

- 變量的作用域和靜態變量
    
    static關鍵字
    ①僅初始化一次
    ②初始化時需要賦值
    ③每次執行函數該值會保留
    ④static修飾的變量是局部的,僅在函數內部有效
    ⑤可以記錄函數的調用次數,從而可以在某些條件下終止遞歸
    
- 函數的引用返回

    從函數返回一個引用,必須在函數聲明和指派返回值給一個變量時都使用引用運算符&
    
    例子:
    function &mgFunc(){
        static $b = 10;
        return $b;
    }
    $a = myFunc();  => 10
    $a = &myFunc();
    $a = 100;
    echo myFunc(); => 100

- 內置函數【簡略】

    看手冊或者之前記錄的函數使用

正則表達式

- 正則表達式的作用:分割、查找、匹配、替換字符串
    相關匹配規則【簡略】

- 後向引用

    $str = '<b>abc</b>';
    $pattern = '/<b>(.*)<\/b>/';
    preg_replace($pattern, '\\1', $str);  => abc
    
- 貪婪模式

    $str = '<b>abc</b><b>abc</b>';
    $pattern = '/<b>.*<\/b>/';
    preg_replace_all($pattern, '\\1', $str);  => abc</b><b>abc
    //取消貪婪模式切換爲懶惰模式
    //① 添加 ? 符號
    $pattern = '/<b>.*?<\/b>/'; => abc
    //② 添加 U
    $pattern = '/<b>.*<\/b>/U'; => abc
    
- 中文匹配
    utf8漢字編碼範圍 0x4e00-0x9fa5,
    ansi(gb2312)是 0xb0-0xf7, 0xa1-0xfe
    
    utf8要使用u模式修正符使模式字符串被當成utf-8,在gb2312環境下,要使用chr將ascii碼轉換爲字符
    
    示例:
    $str = '中文';
    //utf-8
    $pattern = '/[\x{4e00}-\x{9fa5}]+/u';
    //gb2312
    $pattern = '/['. chr(0xb0) . '-' . chr(0xf7) . '][' . chr(0xa1) . '-' . chr(0xfe) . ']/';
    preg_match($pattern, $str, $match);
    var_dump($match);
    
- 模式修飾符
    模式修飾符的作用是設定模式,也就是正則表達式如何解釋。php中主要模式如下表:
    
    修飾符|	說明
    i |	忽略大小寫
    m |	多文本模式
    s |	單行文本模式
    x |	忽略空白字符    
    
- php中的字符串匹配

    不使用正則匹配:
    
        strstr函數 
        string strstr ( string haystack,mixedneedle [, bool $before_needle = false ]) 
        注1:haystack是當事字符串,needle是被查找的字符串。該函數區分大小寫。
        注2:返回值是從needle開始到最後。
        注3:關於$needle,如果不是字符串,被當作整形來作爲字符的序號來使用。
        注4:before_needle若爲true,則返回前東西。
        
        stristr函數與strstr函數相同,只是它不區分大小寫
        
        strpo函數 
        int strpos ( string haystack,mixedneedle [, int $offset = 0 ] ) 
        注1:可選的 offset 參數可以用來指定從 haystack 中的哪一個字符開始查找。返回的數字位置是相對於 haystack 的起始位置而言的。
        
        stripos -查找字符串首次出現的位置(不區分大小定)
        
        strrpos -計算指定字符串在目標字符串中最後一次出現的位置
        
        strripos -計算指定字符串在目標字符串中最後一次出現的位置(不區分大小寫)
        
    使用正則表達式匹配
        
        在php中,提供了preg_math()和preg_match_all函數進行正則匹配。關於這兩個函數原型如下:
        int preg_match|preg_match_all ( string $pattern , string $subject [, array &$matches [, int $flags = 0 [, int $offset = 0 ]]] )
        
        搜索subject與pattern給定的正則表達式的一個匹配.
        
        pattern:要搜索的模式,字符串類型。 
        subject :輸入字符串。 
        matches:如果提供了參數matches,它將被填充爲搜索結果。 matches[0]將包含完整模式匹配到的文本,matches[1]將包含第一個捕獲子組匹配到的文本,以此類推。 
        flags:flags可以被設置爲以下標記值:PREG_OFFSET_CAPTURE 如果傳遞了這個標記,對於每一個出現的匹配返回時會附加字符串偏移量(相對於目標字符串的)。 注意:這會改變填充到matches參數的數組,使其每個元素成爲一個由 第0個元素是匹配到的字符串,第1個元素是該匹配字符串 在目標字符串subject中的偏移量。 
        offset:通常,搜索從目標字符串的開始位置開始。可選參數 offset 用於 指定從目標字符串的某個未知開始搜索(單位是字節)。
        
        返回值:preg_match()返回 pattern 的匹配次數。 它的值將是0次(不匹配)或1次,因爲 preg_match()在第一次匹配後 將會停止搜索。 preg_match_all()不同於此,它會一直搜索subject直到到達結尾。 如果發生錯誤 preg_match()返回 FALSE。

文件/目錄操作


文件
- fopen(), 打開時需要指定打開模式
    打開模式:
    r/r+ (讀/讀寫) 文件指針指向開頭;
    w/w+ (只寫/讀寫) 文件指針指向開頭,清空文件,不存在則創建;
    a/a+  (追加) 文件指針指向末尾, 不存在則創建;
    x/x+ (寫入) 文件指針指向開頭,如果文件存在報warning錯誤,返回false.不存在則新建
    b 二進制文件打開可用
    t 系統提供的文件類型打開模式

    寫入函數: fwrite() 、 fputs()
    讀取函數:fread() fgets() fgetc()
    關閉函數: fclose()

- 不需要fopen打開函數:
    file_get_contents()
    file_put_contents()
    
- 訪問遠程文件
    開啓allow_url_fopen, http連接只能使用只讀, ftp協議只能使用只讀或者只寫

目錄
- 目錄操作函數
    名稱相關:basename()、dirname()、pathinfo()
    目錄讀取:opendir()  readdir()  closedir() rewinddir() 
    目錄刪除:rmdir() 只能刪除空文件
    目錄創建:mkdir() 相關權限設置
- 其他函數
    文件大小:filesize()
    目錄大小:disk_free_space()  disk_total_space()
    文件拷貝:copy()
    刪除文件:unlink()
    文件類型:filetype()
    重命名(移動)文件或者目錄:rename()
    文件截取:ftruncate()
    文件屬性:file_exists()  is_readable() is_wrirtable() is_executable()  filectime()修改時間  fileatime()訪問時間  filemtime()
    文件鎖: flock()
    文件指針:ftell()  fseek()  rewind() 
    
    文件目錄刪除和複製

    示例:
    輸出目錄結果
    function loopDir($dir)
    {
        $handle = openidr($dir);
        while(false!==($file = readdir($handle)))
        {
            if($file != '.' && $file != '..')
            {
                echo $file . '\n';
                if(filetype($dir. '/' . $file) == 'dir') 
                {
                    loopDir($dir. '/' . $file);
                }
            }
        }
    }

會話控制

- 產生的原因
    http每次請求都是握手/揮手,第二次和第一次請求時沒有任何關聯的,屬於無狀態協議,爲了區分用戶才需要會話
- Cookie
    setcookie();
    $_COOKIE
- Session
    session_start();//啓動新會話或者重用現有會話,發送set-cookie的響應頭,告訴瀏覽器設置一個php_session的cookie 會話,會話id爲php隨機產生,並在服務器端臨時目錄產生一個對應的session文件
    $_SESSION['a'] = 1;//存儲一個關於該會話id的值
    session_destroy();//銷燬會話數據
    //當在腳本結束時,會將超全局變量$_SESSION中的值存儲進對應的session文件

面向對象

設計模式

魔術方法

基本語法

網絡協議

相關網絡層協議瞭解

- http協議狀態碼
    2**開頭 (請求成功)表示成功處理了請求的狀態代碼。
    200 (成功) 服務器已成功處理了請求。 通常,這表示服務器提供了請求的網頁。
    201 (已創建) 請求成功並且服務器創建了新的資源。
    202 (已接受) 服務器已接受請求,但尚未處理。
    203 (非授權信息) 服務器已成功處理了請求,但返回的信息可能來自另一來源。
    204 (無內容) 服務器成功處理了請求,但沒有返回任何內容。
    205 (重置內容) 服務器成功處理了請求,但沒有返回任何內容。
    206 (部分內容) 服務器成功處理了部分 GET 請求。
    
    3** 開頭 (請求被重定向)表示要完成請求,需要進一步操作。 通常,這些狀態代碼用來重定向。
    300 (多種選擇) 針對請求,服務器可執行多種操作。 服務器可根據請求者 (user agent) 選擇一項操作,或提供操作列表供請求者選擇。
    301 (永久移動) 請求的網頁已永久移動到新位置。 服務器返回此響應(對 GET 或 HEAD 請求的響應)時,會自動將請求者轉到新位置。
    302 (臨時移動) 服務器目前從不同位置的網頁響應請求,但請求者應繼續使用原有位置來進行以後的請求。
    303 (查看其他位置) 請求者應當對不同的位置使用單獨的 GET 請求來檢索響應時,服務器返回此代碼。
    304 (未修改) 自從上次請求後,請求的網頁未修改過。 服務器返回此響應時,不會返回網頁內容。
    305 (使用代理) 請求者只能使用代理訪問請求的網頁。 如果服務器返回此響應,還表示請求者應使用代理。
    307 (臨時重定向) 服務器目前從不同位置的網頁響應請求,但請求者應繼續使用原有位置來進行以後的請求。
    
    4**開頭 (請求錯誤)這些狀態代碼表示請求可能出錯,妨礙了服務器的處理。
    400 (錯誤請求) 服務器不理解請求的語法。
    401 (未授權) 請求要求身份驗證。 對於需要登錄的網頁,服務器可能返回此響應。
    403 (禁止) 服務器拒絕請求。
    404 (未找到) 服務器找不到請求的網頁。
    405 (方法禁用) 禁用請求中指定的方法。
    406 (不接受) 無法使用請求的內容特性響應請求的網頁。
    407 (需要代理授權) 此狀態代碼與 401(未授權)類似,但指定請求者應當授權使用代理。
    408 (請求超時) 服務器等候請求時發生超時。
    409 (衝突) 服務器在完成請求時發生衝突。 服務器必須在響應中包含有關衝突的信息。
    410 (已刪除) 如果請求的資源已永久刪除,服務器就會返回此響應。
    411 (需要有效長度) 服務器不接受不含有效內容長度標頭字段的請求。
    412 (未滿足前提條件) 服務器未滿足請求者在請求中設置的其中一個前提條件。
    413 (請求實體過大) 服務器無法處理請求,因爲請求實體過大,超出服務器的處理能力。
    414 (請求的 URI 過長) 請求的 URI(通常爲網址)過長,服務器無法處理。
    415 (不支持的媒體類型) 請求的格式不受請求頁面的支持。
    416 (請求範圍不符合要求) 如果頁面無法提供請求的範圍,則服務器會返回此狀態代碼。
    417 (未滿足期望值) 服務器未滿足"期望"請求標頭字段的要求。
    
    5**開頭(服務器錯誤)這些狀態代碼表示服務器在嘗試處理請求時發生內部錯誤。 這些錯誤可能是服務器本身的錯誤,而不是請求出錯。
    500 (服務器內部錯誤) 服務器遇到錯誤,無法完成請求。
    501 (尚未實施) 服務器不具備完成請求的功能。 例如,服務器無法識別請求方法時可能會返回此代碼。
    502 (錯誤網關) 服務器作爲網關或代理,從上游服務器收到無效響應。
    503 (服務不可用) 服務器目前無法使用(由於超載或停機維護)。 通常,這只是暫時狀態。
    504 (網關超時) 服務器作爲網關或代理,但是沒有及時從上游服務器收到請求。
    505 (HTTP 版本不受支持) 服務器不支持請求中所用的 HTTP 協議版本。
  
- OSI七層模型
    物理層: 建立、維護、斷開物理連接
    
    數據鏈路層: 建立邏輯連接、進行硬件地址尋址、差錯校驗等功能
    
    網絡層: 進行邏輯地址尋址、實現不同網絡之間的路徑選擇
    
    傳輸層:定義傳輸數據的協議端口號,以及流控和差錯校驗
    
    會話層:建立、管理、終止會話
    
    表示層:數據的表示、安全、壓縮
    
    應用層: 網絡服務與最終用戶的一個接口
    HTTP FTP TFTP SMTP SNMP DNS TELNET HTTPS POP3 DHCP
    
    
- http協議的工作特點和工作原理

    特點:
    基於b/s模式、通信開銷小、簡單快速、傳輸成本低
    工作原理:
    客戶端發送請求給服務器、創建一個TCP連接,指定端口號, 默認80,連接到服務器,服務器監聽瀏覽器請求,一旦監聽到客戶端請求,分析請求類型後,服務器會向客戶端返回狀態信息和數據內容
    
- 常見的請求、響應頭和請求方法

    http頭部屬性說明:
    Accept 指定客戶端能夠接收的內容類型 Accept: text/plain, text/html
    Accept-Charset 瀏覽器可以接受的字符編碼集。 Accept-Charset: iso-8859-5
    Accept-Encoding 指定瀏覽器可以支持的web服務器返回內容壓縮編碼類型。 Accept-Encoding: compress, gzip
    Accept-Language 瀏覽器可接受的語言 Accept-Language: en,zh
    Accept-Ranges 可以請求網頁實體的一個或者多個子範圍字段 Accept-Ranges: bytes
    Authorization HTTP授權的授權證書 Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
    Cache-Control 指定請求和響應遵循的緩存機制 Cache-Control: no-cache
    Connection 表示是否需要持久連接。(HTTP 1.1默認進行持久連接) Connection: close
    Cookie HTTP請求發送時,會把保存在該請求域名下的所有cookie值一起發送給web服務器。 Cookie: $Version=1; Skin=new;
    Content-Length 請求的內容長度 Content-Length: 348
    Content-Type 請求的與實體對應的MIME信息 Content-Type: application/x-www-form-urlencoded
    Date 請求發送的日期和時間 Date: Tue, 15 Nov 2010 08:12:31 GMT
    Expect 請求的特定的服務器行爲 Expect: 100-continue
    From 發出請求的用戶的Email From: [email protected]
    Host 指定請求的服務器的域名和端口號 Host: www.zcmhi.com
    If-Match 只有請求內容與實體相匹配纔有效 If-Match: “737060cd8c284d8af7ad3082f209582d”
    If-Modified-Since 如果請求的部分在指定時間之後被修改則請求成功,未被修改則返回304代碼 If-Modified-Since: Sat, 29 Oct 2010 19:43:31 GMT
    If-None-Match 如果內容未改變返回304代碼,參數爲服務器先前發送的Etag,與服務器迴應的Etag比較判斷是否改變 If-None-Match: “737060cd8c284d8af7ad3082f209582d”
    If-Range 如果實體未改變,服務器發送客戶端丟失的部分,否則發送整個實體。參數也爲Etag If-Range: “737060cd8c284d8af7ad3082f209582d”
    If-Unmodified-Since 只在實體在指定時間之後未被修改才請求成功 If-Unmodified-Since: Sat, 29 Oct 2010 19:43:31 GMT
    Max-Forwards 限制信息通過代理和網關傳送的時間 Max-Forwards: 10
    Pragma 用來包含實現特定的指令 Pragma: no-cache
    Proxy-Authorization 連接到代理的授權證書 Proxy-Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
    Range 只請求實體的一部分,指定範圍 Range: bytes=500-999
    Referer 先前網頁的地址,當前請求網頁緊隨其後,即來路 Referer: http://www.zcmhi.com/archives...
    TE 客戶端願意接受的傳輸編碼,並通知服務器接受接受尾加頭信息 TE: trailers,deflate;q=0.5
    Upgrade 向服務器指定某種傳輸協議以便服務器進行轉換(如果支持) Upgrade: HTTP/2.0, SHTTP/1.3, IRC/6.9, RTA/x11
    User-Agent User-Agent的內容包含發出請求的用戶信息 User-Agent: Mozilla/5.0 (Linux; X11)
    Via 通知中間網關或代理服務器地址,通信協議 Via: 1.0 fred, 1.1 nowhere.com (Apache/1.1)
    Warning 關於消息實體的警告信息 Warn: 199 Miscellaneous warning
    
    請求方式:
    GET  POST  PUT DELETE  HEAD  OPTION  TRACE
    
- https協議的工作原理
    

PHP常見配置

```
register_globals, allow_url_fopen, allow_url_include, date.timezone, display_errors, erro_reporting, safe_mode, upload_max_filesize, max_file_up

運行模式
php有着5種運行模式,常見的有4種:

cgi 協議模式
cgi模式 通用網關接口(Common Gateway Interface),它允許web服務器通過特定的協議與應用程序通信, 調用原理大概爲:
用戶請求->Web服務器接收請求->fork子進程 調用程序/執行程序->程序返回內容/程序調用結束->web服務器接收內容->返回給用戶 由於每次用戶請求,都得fork創建進程調用一次程序,然後銷燬進程,所以性能較低

fast-cgi 協議模式
fast-cgi是cgi模式的升級版,它像是一個常駐型的cgi,只要開啓後,就可一直處理請求,不再需要結束進程, 調用原理大概爲:
web服務器fast-cgi進程管理器初始化->預先fork n個進程
用戶請求->web服務器接收請求->交給fast-cgi進程管理器->fast-cgi進程管理區接收,給其中一個空閒fast-cgi進程處理->處理完成,fast-cgi進程變爲空閒狀態,等待下次請求->web服務器接收內容->返回給用戶

注意,fast-cgi和cgi都是一種協議,開啓的進程是單獨實現該協議的進程

模塊模式
apache+php運行時,默認使用的是模塊模式,它把php作爲apache的模塊隨apache啓動而啓動,接收到用戶請求時則直接通過調用mod_php模塊進行處理,詳細內容可自行百度

php-cli模式
php-cli模式屬於命令行模式,對於很多剛開始學php就開始wamp,wnmp的開發者來說是最陌生的一種運行模式
該模式不需要藉助其他程序,直接輸入php xx.php 就能執行php代碼
命令行模式和常規web模式明顯不一樣的是:

沒有超時時間
默認關閉buffer緩衝
STDIN和STDOUT標準輸入/輸出/錯誤 的使用
echo var_dump,phpinfo等輸出直接輸出到控制檯
可使用的類/函數 不同
php.ini配置的不同

```

ajax的工作原理

    - XMlHttpRequest對象請求
    open(method, url, async)
    send(string)
    - xmlhttprequest 對象響應

Linux基礎

    系統安全
    進程管理
    w  top ps kill pkill  pstree killall
    用戶管理
    文件系統
    系統關機和重啓
    網絡應用
    網絡配置
    軟件包管理
    文件查找和比較
    文件內容查看
    文件處理
    文件權限
    解壓壓縮
    
    - crontab 定時任務
    crontab -e 
    (分時日月周)
    
    - vim、vi 編輯器
    一般模式、編輯模式、命令行模式
    一般模式:刪除、複製、粘貼
    配置:命令行模式下 setnu setnonu 顯示行數
    
    -  shell基礎
    賦予權限,直接執行:
    chmod +x test.sh
    ./test.sh
    
    使用source命令,例:
    source test.sh

練手

  • 題目
1. 以下程序$data值是多少?(引用)

    $data = ['a', 'b', 'c'];
    foreach($data as $key => $val) 
    {
        $val = &$data[$key];
    }

2. 以下比較返回什麼?(浮點類型不能用於比較運算)
    $a = 0.1;
    $b = 0.7;
    return $a + $b ==  0.8;

3. _FILE_ 表示什麼意思(預定義常量)

4. false 的七種情況

5. $a  和 $b 的值是什麼?
    $a = false || true;
    $b = false or true;

6. 打印輸出的結果是什麼?

    $a = 0;
    $b = 0;
    if ($a = 3 > 0 || $b = 3 > 0) 
    {
        $a++;
        $b++;
        echo $a;
        echo $b;
    }

7. php遍歷數組的三種方式及各自區別

8. PHP中如何優化多個if....elseif語句的情況?

9. 以下程序的輸出結果?

    $count = 5;
    function get_count()
    {
        static $count;
        return $count++;
    }
    echo $count;
    ++$count;
    
    echo get_count():
    echo get_count():
 
10. 寫出139開頭的11位手機號的正則表達式

11. 請匹配所有img標籤中的src值

12. 每天0點重啓服務器定時任務

  • 答案
1. $data = ['b', 'c', 'c']; //引用傳值會修改原先的引用變量值內存

2. false //浮點型會轉換爲二進制,0.7轉爲二進制時會有損耗,兩者相加等於 0.79999

3. 所在文件的路徑以及文件名

4, 看筆記

5. 運算符的優先級

    $a = true;
    $b = false;
    
    第二個表達式中,= 賦值運算符優先於or 整體運算是 true
    
6. 運算符的優先級
    $a = 1;
    $b = 1;
    
7. 看筆記

8. 表達式可能越大往前放。如果是簡單的表達式可考慮使用switch。

9. 5  null  1 //自定義函數中的初始化$count時值爲null

10. 如下: 
    $str = '139888888888';
    $pattern = '/^139\d{8}$/' // ^ 以139開頭,後面以0到9數字的8位數字, $結束
    preg_match($pattern, $str, $mattch);
    
11. 如下
    $pattern = '/<img.*?src=".*?".*?\/?>/i';//匹配img標籤內容 /i 標識不區分大小寫
    $pattern = '/<img.*?src="(.*?)".*?\/?>/i';//匹配src的值
    preg_match($pattern, $str, $match);
    var_dump($match);

12. crontab -e
    添加以下一列:
    0 0 * * * reboot
    分 時 日 月 周

MYSQL

having 和 where

where針對表中的列發揮作用,查詢數據

having對查詢結果中的列發揮作用,篩選數據

數據類型

    - 實數類型
    FLOAT, DOUBLE, DECIMAL
    DECIMAL 可存儲比BIGINT還大的整數, 可以用於存儲精確的小數
    FLOAT,DOUBLE支持使用標準的浮點進行近似運算
    
    - 字符串類型
    VARCHAR, CHAR, TEXT, BLOB 
    VARCHAR 用於存儲可變長字符串, 它比定長類型更節省空間
    VARCHAR 使用1或2個額外字節記錄字符串的長度,列長度小於255字節,使用1個字節表示,否則用2個
    VARCHAR長度如果存儲內容長度超出指定長度,會被截斷
    CHAR是定長的,根據定義的字符串長度分配足夠的空間
    CHAR會根據需要採用空格進行填充以方便比較
    CHAR適合存儲很短的字符串,或者所有值接近同一個長度(密碼)
    CHAR長度超出設定長度也會被截斷
    頻繁更新的數據,CHAR比VARCHAR更好,不容易產生碎片
    對於非常短的列,CHAR比VACHAR在存儲空間上更有效率
    只分配真正需要的空間,更長的列會消耗更多的內存

    - 枚舉
    把不重複的集合存儲成一個預定義的集合
    非常緊湊,把列表值壓縮到一個或字節
    內部存儲的是整數
    排序是按照內部存儲的整數進行排序的
    
    - 日期和時間類型
    儘量使用TIMESTAMP,比 DATETIME 空間效率高
    用整數保存時間戳的格式通常不方便處理
    如果需要存儲微妙, 可以使用bigint存儲
    

索引

    - 對性能的影響
    大大減少服務器需要掃描的數據量
    幫助服務器避免排序和臨時表
    將隨機I/O變順序I/O
    大大提高查詢速度,降低寫的速度,佔用磁盤

    - 索引類型
    一個表只能有一個主鍵索引,可以有多個唯一索引
    主鍵索引一定是唯一索引, 唯一索引不是主鍵索引
    主鍵可以與外鍵構成參照完整性約束,防止數據不一致
    組合索引:將多列組合在一起創建索引,可以覆蓋多個列
    外鍵索引:只有InnoDB類型的表纔可以使用外鍵索引,保證數據的一致性,完整性和實現級聯操作
    全文索引:MySql自帶的全文索引只能用於MyISAM,並且只能對英文進行全文檢索
    
    - 創建原則
    1. 最適合索引的列是出現在WHERE子句中的列,或連接子句中的列而不是出現在select關鍵字後的列
    2. 索引列的基數越大,索引的效果越好
    3. 對字符串進行索引,應該定製一個前綴長度,可以節省大量的索引空間
    4. 根據情況創建複合索引,複合索引可以提高查詢效率
    5. 避免創建過多索引, 索引會額外佔用磁盤空間,降低寫操作效率
    6. 主鍵儘可能選擇較短的數據類型,可以有效減少索引的磁盤佔用,提高查詢效率
    
    - 注意:
    1. 複合索引遵循的前綴原則
    例:複合索引的連續性
    KEY(a, b, c) 組合索引 abc  有效查詢如下
    WHERE a = 1 and b = 2 and c = 3
    WHERE a = 1 and b = 2
    WHERE a = 1
    無效查詢
    WHERE b = 2 and c = 3
    WHERE a = 1 and c = 3
    
    2. like 查詢 %不能在前,否則索引失效,可以使用全文索引
    3. column is null 可以使用索引
    4. 如果MYSQL估計使用索引比全表掃描更慢, 會放棄使用索引
    5. 如果or前的條件中的列有索引,後面的沒有,索引都不會被用到
    6. 列類型是字符串,查詢時一定要給值加引導, 否則索引失效
    例:
    name varchar(18)類型
    “100”
    where name = 100 時不會使用索引
    where name = “100"時纔會生效
    
    

mysql操作

    例:有A(id, sex, par, c1, c2) , B(id, age, c1, c2)兩張表,其中A.id 同 B.id 關聯, 現要求寫出一條Sql語句,將B中age>50的記錄的c1, c2 更新到A表中統一記錄中的C1, c2字段中
    
    - update更新語句
        UPDATE A,B SET A.c1 = B.c1, A.c2= B.c2 WHERE A.id = B.id and B.age > 50;
        UPDATE A INNER JION B ON A.id = B.id SET A.c1 = B.c1, A.c2 = B.c2 WHERE B.age > 50;
    
    - 聯合查詢
        union 就是把多個結果集集中在一起,以union前的結果爲基準,需要注意的是聯合查詢的列數要相等,相同的記錄行會合並
        如果使用union all 不會合並重復的記錄行
    
    - 全連接
        mysql不支持全連接
        可以使用左連接和右連接聯合使用
        SELECT * FROM A LEFT JOIN B ON A.id = B.id UNION SELECT * FROM A RIGHT JOIN B ON A.id = B.id;
    
    - 例子
        表team
        teamID teamName
        表match
        matchID
        hostTeamId guestTeamID matchTime matchResult 
        根據以上兩張表按如下格式查出
        主隊  結果  客隊  時間
        
        SELECT t1.teamName, m.matchResult, t2.teamName, m.matchTime from match as m left join team as t1 on m.hostTeamID = t1.teamID, left join team t2 on m.guestTeamID = t2.gteamID where m.matchTime between "2006" and "2017";
    
    - mysql 優化
        1. 分析 sql 查詢慢的方法
        記錄慢查詢日誌
        ① 分析查詢日誌,使用pt-query-digest工具進行分析
        
        ② 使用show profile
        set profiling = 1; 開啓,服務器上執行的所有語句會檢測消耗的時間,存到臨時表中
        show profiles;
        show profile for query 臨時表id;
        
        ③ 使用show status
        show status 會返回一些計數器,show global status 查看服務器級別的所有計數
        
        ④ 使用 show processlist
        觀察是否有大量線程處於不正常的狀態或者特徵
        
        ⑤ 使用 explain 或者 desc 
        分析單挑sql語句
        explain select * from a; 可查看索引使用情況,掃描行數
        
        2. 優化查詢過程中的數據訪問
        訪問數據太多導致查詢性能下降
        
        ① 查詢不需要的記錄,使用limit解決
        ② 多表關聯返回全部列,指定 A.id , A.name, B.age
        ③ 總是取出全部列,SELECT * 會讓優化器無法完成索引覆蓋掃描的優化
        ④ 重複查詢相同的數據,可以緩存數據, 下次直接讀取緩存
        ⑤ 是否存在掃描額外的記錄
        使用explain 進行分析, 如果發現查詢需要掃描大量的數據但只返回少數的行可做如下操作:
        使用索引覆蓋掃描, 把所有用的列都放到索引中,這樣存儲引擎不需要回表獲取對應行就可以返回結果
        ⑥ 該表數據庫和表的結構,修改數據表範式,添加冗餘字段減少關聯查詢
        
        3. 優化長難的查詢語句
        ① 切分查詢
        將一個大的查詢分爲多個小的相同的查詢
        一次性刪除1000w的數據要比一次刪除1w,暫停一會的方案更加損耗服務器開銷
        
        ② 分解關聯查詢
        可以將一條關聯語句分解成多條sql來執行,作用如下:
        讓緩存的效率更高
        執行單個查詢可以減少鎖的競爭
        在應用層做關聯可以更容易對數據庫進行拆分
        
        4. 優化特定類型的查詢語句
        
        ①優化count() 查詢
        count() 中的* 會忽略所有的列,直接統計所有列數,因此不要使用count(列名)
        
        ② 優化關聯查詢
        確定 on 或 using 子句的列上有索引
        確保group by 和 order by 只有一個表中的列,這樣mysql纔有可能使用索引
        
        ③ 優化子查詢,使用關聯查詢來替代
        
        ④ 優化group by 和 distinct 
        這兩種查詢均可使用索引來優化,是最有效的優化方法
        關聯查詢中,使用標識列進行分組的效率會更高
        如果不需要order by,進行group by 時使用order by null ,mysql不會再進行文件排序
        
        ⑤ 優化limit分頁
        limit 偏移量大的時候,查詢效率較低
        可以記錄上次查詢的最大id,下次查詢時直接根據該id來查詢
        
        ⑥ 優化union 查詢
        union all 的效率高於 union 
    
    - 分表
        1. 分區表的原理
        
        工作原理:創建表時使用partition by 子句定義每個分區存放的數據,執行查詢時,優化器會根據分區定義過濾那些沒有我們需要數據的分區,這樣查詢只需要查詢所需數據在的分區即可
        
        限制:
            1. 一個表最多只能有1024個分區
            2. 分區字段中如果存在主鍵或者唯一索引列, 都必須包含進來
            3. 分區表中無法使用外鍵約束
            4. 需要對現有表的結構進行修改
            5. 所有分區都必須使用相同的存儲引擎
            
        2. 分庫分表的原理
        工作原理:通過一些hash算法活工具實現將一張數據表垂直或者水平進行物理切分
        
        使用場景:
            1. 單表記錄條數達到百萬至千萬級別時
            2. 解決表鎖‘
        
        分表方式:
            水平分割
            缺點:
            ① 給應用增加複雜度,通常查詢時需要多個表名,查詢所有數據都需要union操作
            ② 在許多數據庫應用中,這種複雜性會超過它帶來的優點,查詢時會增加讀一個索引層的磁盤次數
            
            垂直分表
            把主鍵和一些列放在一個表,然後把主鍵和另外的列放在另外一個表中
            使用場景:
            ① 如果一個表中某些列常用,而另外一些列不常用
            ② 可以使數據行變小,一個數據頁能存儲更多數據,查詢時減少I/o次數
            
            缺點:
            ① 管理冗餘列,查詢所有數據需要join操作
            
    - 複製原理以及負載均衡    
    
        mysql 主從複製工作原理
            在主庫上把數據更改記錄到二進制日誌,從庫將主庫的日誌複製到自己的中繼日誌,從庫讀取中繼日誌中的事件,將其重放到從庫數據中
            
        mysql主從複製解決的問題
        數據分佈:隨意停止或開始複製,並在不同地理位置分佈數據備份
        負載均衡:降低單個服務器的壓力
        
    - mysql 安全     
    1. 使用預處理語句處理sql語句,防止sql注入
    2. 寫入數據庫的數據要進行特殊字符的轉義
    3. 查詢錯誤的信息不要返回給用戶, 將錯誤記錄到日誌
    
    - PHP操作數據庫代碼
    $dsn = 'mysql:dbname=test;host=localhost';
    $Username = 'test';
    $password = 'test';
    $attr  = [
        PDO::ATTR_ERRMODE => PDOERRMODE_EXCEPTION
    ];
    $pdo = new PDO($dsn, $username, $password, $attr);
    //$sql = 'SELECT id, title, content FROM message where user_name = :user_name' ;
    $sql = 'INSERT INTO message(title, content, create_at, user_name) values (:title, :content, :create_at, :user_name)';
    $stmt = $pdo->prepare($sql);
    $data = [
        ':title' => $title,
        ....
    ];
    $stmt->execute($data);
    $rows = $stmt->rowCount();
    if($rows){
        exit('添加成功');
    } else {
        exit('添加失敗')
    }
    //$result = $stmt->fetchAll(PDO::FETCH_ASSOC);
    

練手

1. having 和 where
#查詢兩門及兩門以上科目不及格的學生的平均分
思路:
#先計算所有學生的平均分
select name,avg(score) as pj from stu group by name;
#查出所有學生的掛科情況
select name,score<60 from stu;
#這裏score<60是判斷語句,所以結果爲真或假,mysql中真爲1假爲0
#查出兩門及兩門以上不及格的學生
select name,sum(score<60) as gk from stu group by name having gk > 1;
#綜合結果
select name,sum(score<60) as gk,avg(score) as pj from stu group by name having gk >1;

2. 

算法

    時間複雜度計算方式:T(n) = O(f(n))
        用常熟1取代所有時間中的所有加法常數
        在修改後的運行次數函數中,只保留最高階項
        如果最高階存在且不是1,則去除與這個項相乘的常數
        一般指最壞情況的時間複雜度
    舉例:
    常數階:O(1)
    線性階:O(n)
    平(立)方階:O(n^2)/O(n^3)
    對數階:O(log2n)
    
    空間複雜度:算法要消耗的內存空間,S(n) = O(f(n))
    包括程序代碼所佔用的空間,輸入數據所佔用的空間,輔助變量所佔用的空間這三個方面
    計算和表示方法與時間複雜度類似,一般用複雜度的漸進性來表示
    
    冒泡排序元素交換,空間複雜度O(1) 
    快速排序、歸併排序的理想時間複雜度都是O(nlog2n), 但是快速排序的時間複雜度並不穩定,最壞情況下複雜度爲O(n^2),所以最理想的算法還是歸併排序

冒泡排序

 /**
   * 冒泡排序
   * bubble sort algorithm
   * 
   * @param  array $value 待排序數組 the array that is waiting for sorting
   * @return array
   */
  function bubble($value = [])
  {
      $length = count($value) - 1;
      // 外循環
      // outside loop
      for ($j = 0; $j < $length; ++$j) {
          // 內循環
          // inside loop
          for ($i = 0; $i < $length; ++$i) {
              // 如果後一個值小於前一個值,則互換位置
              // if the next value is less than the current value, exchange each other.
              if ($value[$i + 1] < $value[$i]) {
                  $tmp = $value[$i + 1];
                  $value[$i + 1] = $value[$i];
                  $value[$i] = $tmp;
              }
          }
      }
      return $value;
  }


  /**
   * 優化冒泡排序
   * optimized bubble sort algorithm
   * 
   * @param  array $value 待排序數組 the array that is waiting for sorting
   * @return array
   */
  function bubble_better($value = [])
  {
    $flag   = true; // 標示 排序未完成 the flag about the sorting is whether or not finished.
    $length = count($value)-1; // 數組最後一個元素的索引 the index of the last item about the array.
    $index  = $length; // 最後一次交換的索引位置 初始值爲最後一位 the last exchange of index position, default value is equal to the last index.
    while ($flag) {
      $flag = false; // 假設排序已完成 let's suppose the sorting is finished.
      for ($i=0; $i < $index; $i++) {
        if ($value[$i] > $value[$i+1]) {
          $flag  = true; // 如果還有交換髮生,則排序未完成  if the exchange still happen, it show that the sorting is not finished. 
          $last  = $i; // 記錄最後一次發生交換的索引位置 taking notes the index position of the last exchange.
          $tmp   = $value[$i];
          $value[$i] = $value[$i+1];
          $value[$i+1] = $tmp;
        }
      }
      $index = !$flag ? : $last;
    }
    return $value;
  }

快速排序

<?php
/**
 * php算法實戰.
 *
 * 排序算法-快速排序
 *
 * @author TIGERB <https://github.com/TIGERB>
 */
 /**
  * 快速排序.
  *
  * @param  array $value 待排序數組
  * @param  array $left  左邊界
  * @param  array $right 右邊界
  *
  * @return array
  */
  function quick(&$value, $left, $right)
  {
    // 左右界重合 跳出
    if ($left >= $right) {
      return;
    }
    $base = $left;
    do {
      // 從最右邊開始找到第一個比基準小的值,互換位置
      // 找到基準索引爲止
      for ($i=$right; $i > $base; --$i) {
        if ($value[$i] < $value[$base]) {
          $tmp = $value[$i];
          $value[$i] = $value[$base];
          $value[$base] = $tmp;
          $base = $i; // 更新基準值索引
          break;
        }
      }
      // 從最左邊開始找到第一個比基準大的值,互換位置
      // 找到基準索引爲止
      for ($j=$left; $j < $base; ++$j) {
        if ($value[$j] > $value[$base]) {
          $tmp = $value[$j];
          $value[$j] = $value[$base];
          $value[$base] = $tmp;
          $base = $j; // 更新基準值索引
          break;
        }
      }
    } while ($i > $j);// 直到左右索引重合爲止
    // 開始遞歸
    // 以當前索引爲分界
    // 開始排序左部分
    quick($value, $left, $i-1);
    // 開始排序右邊部分
    quick($value, $i+1, $right);
    return $value;
  }
  /**
   * 快速排序.while版本
   *
   * @param  array $value 待排序數組
   * @param  array $left  左邊界
   * @param  array $right 右邊界
   *
   * @return array
   */
  function quick_while(&$value, $left, $right)
  {
    // 左右界重合 跳出
    if ($left >= $right) {
      return;
    }
    $point = $left;
    $i = $right;
    $j = $left;
    while ($i > $j) {
      //查右邊值
      while ($i > $point) {
        if ($value[$i] < $value[$point]) {
          $tmp = $value[$i];
          $value[$i] = $value[$point];
          $value[$point] = $tmp;
          $point = $i;
          break;
        }
        --$i;
      }
      //查左邊值
      while ($j < $point) {
        if ($value[$j] > $value[$point]) {
          $tmp = $value[$j];
          $value[$j] = $value[$point];
          $value[$point] = $tmp;
          $point = $j;
          break;
        }
        ++$j;
      }
    }
    // 開始遞歸
    // 以當前索引爲分界
    // 開始排序左部分
    quick_while($value, $left, $i-1);
    // 開始排序右邊部分
    quick_while($value, $i+1, $right);
    return $value;
  }

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