python 之 資料庫(內置函數、流程式控制制、索引)

来源:https://www.cnblogs.com/mylu/archive/2019/08/08/11324151.html
-Advertisement-
Play Games

10.17 內置函數 強調:mysql內置的函數只能在sql語句中使用 date_format: 10.171 自定義函數 函數中不要寫sql語句(否則會報錯),函數僅僅只是一個功能,是一個在sql中被應用的功能,若要想在begin...end...中寫sql,請用存儲過程. 刪除函數: 執行函數: ...


10.17 內置函數

強調:mysql內置的函數只能在sql語句中使用

#數學函數
round(x,y)      #返回參數x的四捨五入的有y位小數的值
rand()          #返回0到1內的隨機值,可以通過提供一個參數(種子)使rand()隨機數生成器生成一個指定的值。
​
#加密函數
md5()           #計算字元串str的MD5校驗和
password(str)   #返回字元串str的加密版本,這個加密過程是不可逆轉的,和UNIX密碼加密過程使用不同的演算法。

date_format:

create table blog (
    id int primary key auto_increment,
    name char (32),
    sub_time datetime);
insert into blog (name, sub_time) values
('第1篇','2015-03-01 11:31:21'),
('第2篇','2015-03-11 16:31:21'),
('第3篇','2017-05-01 18:31:21');
select date_format(sub_time,'%Y-%m'),count(id) from blog group by date_format(sub_time,'%Y-%m');
+-------------------------------+-----------+
| date_format(sub_time,'%Y-%m') | count(id) |
+-------------------------------+-----------+
| 2015-03                       |         2 |
| 2017-05                       |         1 |
+-------------------------------+-----------+

10.171 自定義函數

函數中不要寫sql語句(否則會報錯),函數僅僅只是一個功能,是一個在sql中被應用的功能,若要想在begin...end...中寫sql,請用存儲過程.

delimiter //
create function f1(
    i1 int,
    i2 int)
returns int
BEGIN
    declare num int;
    set num = i1 + i2;
    return(num);
END //
delimiter ;

刪除函數:

drop function func_name;

執行函數:

# 獲取返回值
select UPPER('egon') into @res;
SELECT @res;
+------+
| @res |
+------+
| EGON |
+------+
# 在查詢中使用
select f1(11,nid) ,name from tb2;

10.18 流程式控制制

if條件語句:

delimiter //
create function f5(i int)
returns int
begin
    declare res int default 0;
    if i = 10 then
        set res=100;
    elseif i = 20 then
        set res=200;
    elseif i = 30 then
        set res=300;
    else
        set res=400;
    end if;
    return res;
end //
delimiter ;

控制流函數:

select 
case
    when name = 'egon' then name
    when name = 'alex' then concat(name,'_BIGSB')
    else concat(name,'_SB')
end
from emp;

迴圈語句:

delimiter //
create procedure proc_while ()
begin
    declare num int ;
    set num = 0 ;
    while num < 10 do
        select
            num ;
        set num = num + 1 ;
    end while ;
end //
delimiter ;

10.19 索引

索引就相當於書的目錄,是mysql中一種專門的數據結構,稱為key, 索引的本質原理就是通過不斷地縮小查詢範圍,來降低 i/o 次數從而提升查詢性能,一旦為表創建了索引,以後的查詢都會先查索引,再根據索引定位的結果去找數據

索引的影響: 1、在表中有大量數據的前提下,創建索引速度會很慢 2、在索引創建完畢後,對錶的查詢性能會大幅度提升,但是寫性能會降低

聚集索引(primary key):就是按照每張表的主鍵構造一棵B+樹,同時葉子結點存放的即為整張表的行記錄數據,也將聚集索引的葉子結點稱為數據頁。聚集索引的這個特性決定了索引組織表中數據也是索引的一部分。同B+樹數據結構一樣,每個數據頁都通過一個雙向鏈表來進行鏈接。特點:葉子節點存放的一整條數據

聚集索引的優點:1.它對主鍵的排序查找和範圍查找速度非常快,葉子節點的數據就是用戶所要查詢的數據。如用戶需要查找一張表,查詢最後的10位用戶信息,由於B+樹索引是雙向鏈表,所以用戶可以快速找到最後一個數據頁,並取出10條記錄 2.範圍查詢(range query),即如果要查找主鍵某一範圍內的數據,通過葉子節點的上層中間節點就可以得到頁的範圍,之後直接讀取數據頁即可


輔助索引(unique,index):非聚集索引即從輔助索引中就可以得到查詢記錄,而不需要查詢聚集索引中的記錄。 特點:輔助索引的葉子節點不包含行記錄的全部數據。如果是按照name欄位創建的索引,那麼葉子節點存放的是:{name:名字所在那條記錄的主鍵的值}

每張表上可以有多個輔助索引,但只能有一個聚集索引。當通過輔助索引來尋找數據時,InnoDB存儲引擎會遍歷輔助索引並通過葉子級別的指針獲得主鍵索引的主鍵,然後再通過主鍵索引來找到一個完整的行記錄。

使用覆蓋索引的一個好處是:輔助索引不包含整行記錄的所有信息,故其大小要遠小於聚集索引,因此可以減少大量的IO操作,InnoDB存儲引擎支持覆蓋索引(covering index,或稱索引覆蓋),即從輔助索引中就可以得到查詢記錄,而不需要查詢聚集索引中的記錄。

#覆蓋索引:在輔助索引的葉子節點中就已經找到了所有我們想要的數據
select name from user where name='egon';
#非覆蓋索引:命中輔助索引,但是未覆蓋索引,還需要從聚集索引中查找age
select age from user where name='egon'; 

聯合索引:聯合索引指對錶上的多個列合起來做一個索引,在第一個鍵相同的情況下,已經對第二個鍵進行了排序處理

mysql中的primary key,unique,index ,聯合唯一也都是索引,這些索引除了加速查找以外,還有約束的功能

普通索引 index:加速查找
唯一索引:
    -主鍵索引 primary key:加速查找+約束(not null  + unique-唯一索引 unique:加速查找+約束(不能重覆)
聯合索引:
    -primary key(id,name):聯合主鍵索引,加速查找+約束
    -unique(id,name):聯合唯一索引,加速查找+約束
    -index(id,name):聯合普通索引

innodb:聚集索引,輔助索引 myisam:輔助索引

10.191 創建和刪除索引

#方式一
create table t1(
    id int,
    name char,
    age int,
    sex enum('male','female'),
    unique key uni_id(id),
    index ix_name(name)         #index沒有key
);
#方式二
create index ix_age on t1(age);
#方式三
alter table t1 add index ix_sex(sex);
alter table t1 add primary key(id);
#聯合索引
alter table t1 add primary key(id,name);
create index ix_age on t1(id,age);
+-------+-----------------------+------+-----+---------+-------+
| Field | Type                  | Null | Key | Default | Extra |
+-------+-----------------------+------+-----+---------+-------+
| id    | int(11)               | YES  | UNI | NULL    |       |
| name  | char(1)               | YES  | MUL | NULL    |       |
| age   | int(11)               | YES  | MUL | NULL    |       |
| sex   | enum('male','female') | YES  | MUL | NULL    |       |
+-------+-----------------------+------+-----+---------+-------+
#刪除索引:
drop index idx_name on t1;
alter table t1 drop primary key;
​
and工作原理:對於連續多個and:mysql會按照聯合索引,從左到右的順序找一個區分度高的索引欄位(這樣便可以快速鎖定很小的範圍),加速查詢
or的工作原理:對於連續多個or:mysql會按照條件的順序,從左到右依次判斷,此時應該按照區分度高低設置聯合索引

10.192 正確使用索引

10.1921 索引未命中

並不是說我們創建了索引就一定會加快查詢速度,若想利用索引達到預想的提高查詢速度的效果,我們在添加索引時,必須遵循以下問題

1 範圍問題,或者說條件不明確,條件中出現這些符號或關鍵字:>>=<<=!=between...and...、like2 儘量選擇區分度高的列作為索引,區分度的公式是count(distinct col)/count(*),表示欄位不重覆的比例,比例越大我們掃描的記錄數越少,唯一鍵的區分度是1,而一些狀態、性別欄位可能在大數據面前區分度就是0,那可能有人會問,這個比例有什麼經驗值嗎?使用場景不同,這個值也很難確定,一般需要join的欄位我們都要求是0.1以上,即平均1條掃描10條記錄
3 =和in可以亂序,比如a = 1 and b = 2 and c = 3 建立(a,b,c)索引可以任意順序,mysql的查詢優化器會幫你優化成索引可以識別的形式
4 索引列不能參與計算,保持列“乾凈”,比如from_unixtime(create_time) =2014-05-29’就不能使用到索引,原因很簡單,b+樹中存的都是數據表中的欄位值,但進行檢索時,需要把所有元素都應用函數才能比較,顯然成本太大。所以語句應該寫成create_time = unix_timestamp(’2014-05-29’)
5 and/or
#1、and與or的邏輯
    條件1 and 條件2:所有條件都成立才算成立,但凡要有一個條件不成立則最終結果不成立
    條件1 or 條件2:只要有一個條件成立則最終結果就成立
#2、and的工作原理
    條件:
        a = 10 and b = 'xxx' and c > 3 and d =4
    索引:
        製作聯合索引(d,a,b,c)
    工作原理:
        對於連續多個and:mysql會按照聯合索引,從左到右的順序找一個區分度高的索引欄位(這樣便可以快速鎖定很小的範圍),加速查詢,即按照d—>a->b->c的順序
#3、or的工作原理
    條件:
        a = 10 or b = 'xxx' or c > 3 or d =4
    索引:
        製作聯合索引(d,a,b,c)       
    工作原理:
        對於連續多個or:mysql會按照條件的順序,從左到右依次判斷,即a->b->c->d,所以應該將區分度高的放在前面
 6 最左首碼匹配原則,非常重要的原則,對於組合索引mysql會一直向右匹配直到遇到範圍查詢(><betweenlike)就停止匹配(指的是範圍大了,有索引速度也慢),比如 a = 1 and b = 2 and c > 3 and d = 4 如果建立(a,b,c,d)順序的索引,d是用不到索引的,如果建立(a,b,d,c)的索引則都可以用到,a,b,d的順序可以任意調整。所以建立索引時將關於範圍比較的欄位放在後面
7 其他情況
- 使用函數
    select * from tb1 where reverse(email) = 'egon';           
- 類型不一致
    如果列是字元串類型,傳入條件是必須用引號引起來,不然...
    select * from tb1 where email = 999;  
#排序條件為索引,則select欄位必須也是索引欄位,否則無法命中
- order by
    select name from s1 order by email desc;
    當根據索引排序時候,select查詢的欄位如果不是索引,則速度仍然很慢
    select email from s1 order by email desc;
    特別的:如果對主鍵排序,則還是速度很快:
    select * from tb1 order by nid desc;
- 組合索引最左首碼
    如果組合索引為:(name,email)
    name and email       -- 命中索引
    name                 -- 命中索引
    email                -- 未命中索引
- count(1)或count(列)代替count(*)在mysql中沒有差別了
- create index xxxx  on tb(title(19)) #text類型,必須制定長度
索引未命中
10.1922 其他註意事項
1 避免使用select *
2 count(1)或count(列) 代替 count(*)
3 創建表時儘量時 char 代替 varchar
4 表的欄位順序固定長度的欄位優先
5 組合索引代替多個單列索引(經常使用多個條件查詢時)
6 儘量使用短索引
7 使用連接(JOIN)來代替子查詢(Sub-Queries)
8 連表時註意條件類型需一致
9 索引散列值不適合建索引,例:性別不適合

總結:

  1. 一定是為搜索條件的欄位創建索引,比如select * from s1 where id = 333;就需要為id加上索引

  2. 在表中已經有大量數據的情況下,建索引會很慢,且占用硬碟空間,建完後查詢速度加快

  3. 需要註意的是:innodb表的索引會存放於s1.ibd文件中,而myisam表的索引則會有單獨的索引文件table1.MYI

10.193 慢查詢優化的基本步驟

0.先運行看看是否真的很慢,註意設置SQL_NO_CACHE
1.where條件單表查,鎖定最小返回記錄表。這句話的意思是把查詢語句的where都應用到表中返回的記錄數最小的表開始查起,單表每個欄位分別查詢,看哪個欄位的區分度最高
2.explain查看執行計劃,是否與1預期一致(從鎖定記錄較少的表開始查詢)
3.order by limit 形式的sql語句讓排序的表優先查
4.瞭解業務方使用場景
5.加索引時參照建索引的幾大原則
6.觀察結果,不符合預期繼續從0分析

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 下標 所謂下標就是編號,就好比超市中存儲櫃的編號,通過這個編號就能找到相應的存儲空間。 Python中字元串,列表,元祖均支持下標索引。 例如: 切片 切片是指對操作的對象截取一部分的操作,字元串,列表,元組均支持切片操作。 切片的語法:[起始:結束:步長] 註意:選取的區間屬於左閉右開型,即從"起 ...
  • C++Primer在132頁的提示中說:除非必須,否則不用遞增遞減運算符的後置版本 ...
  • 實現流程 這裡我將這個功能抽象成一個面具載入服務,請跟隨我的代碼一窺究竟吧。 1.導入對應的工具包 from time import sleep import cv2 import numpy as np from PIL import Image from imutils import face_ ...
  • 5.1 模塊基礎知識 模塊(類庫)分類 內置模塊,python內部提供的功能 import sys # 優先導入模塊載入到記憶體print(sys,argv) 第三方模塊,下載、安裝、使用 1.pip包管理工具 把pip.exe 所在的文件目錄加到環境變數中 pip install 要安裝的模塊名稱 ...
  • 單例模式:(說白了就是)創建一個類的實例。在 Python 中,我們可以用多種方法來實現單例模式: 1、文件導入的形式(常用) 2、基於類實現的單例模式 3、基於__new__實現的單例模式(最常用 推薦使用,方便) 4、基於metaclass(元類)實現的單例模式 簡單總結 1. 單例只有一個實例 ...
  • 一、常見的集合有哪些? Map 介面和 Collection 介面是所有集合框架的父介面。 1、Collection 介面的子介面包括:Set 介面和 List 介面; 2、Map 介面的實現類主要有:HashMap、TreeMap、Hashtable、ConcurrentHashMap 以及 Pr ...
  • 出自公眾號:大飛碼字 “怎樣才能進大廠?” “我是一個二本電腦專業的學生,怎樣才能進大廠?” “我是一個非電腦專業的學生,有機會可以進大廠嗎?” 我收到不少咨詢如何進大廠的問題,以上是一些比較典型的提問。 “怎麼可以進大廠” 這個問題,跟“怎麼可以在30歲前賺到1000萬” 和 “怎麼可以在40 ...
  • 問題描述 每一本正式出版的圖書都有一個ISBN號碼與之對應,ISBN碼包括9位數字、1位識別碼和3位分隔符,其規定格式如“x-xxx-xxxxx-x”,其中符號“-”是分隔符(鍵盤上的減號),最後一位是識別碼,例如0-670-82162-4就是一個標準的ISBN碼。ISBN碼的首位數字表示書籍的出版 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...