日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

数据库压力测试

發布時間:2024/3/13 数据库 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 数据库压力测试 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一、 存儲過程和觸發器實驗

  • 請在你選用的數據庫平臺上,針對你的應用場景,對如下操作至少各實現一個存儲過程:
    1)單表或多表查詢 2)數據插入 3)數據刪除 4)數據修改
    1)單表查詢,結果如下:
  • –查詢u_id大于輸入的num的
    drop procedure if exists sl;
    – 如果存在就drop
    delimiter //
    – 定義為碰到//才表示語句結束
    create procedure sl(num int)
    begin
    select * from User_tbl where u_id > num;
    end //
    delimiter ;
    – 定義為碰到;表示語句結束
    call sl(5);
    多表查詢結果如下:
    查找u_id為輸入的n的用戶的朋友圈內容和他的真實姓名

    drop procedure if exists lo;
    – 如果存在就drop
    delimiter //
    create procedure lo(n int)
    begin
    select p_content,u_truename from User_tbl,Circlemsg_tbl
    where user_tbl.u_id=n
    and circlemsg_tbl.p_uid=n;
    end //
    delimiter ;
    call lo(6);
    2)數據插入
    drop procedure if exists sp1;
    – 如果存在就drop
    delimiter //
    – 定義為碰到//才表示語句結束
    create procedure sp1(in account varchar(255),in password varchar(255),in name varchar(255),in tname varchar(255),in sex varchar(255))
    begin
    insert into user_tbl(u_account,u_password,u_registtime,u_lock,u_style,u_username,u_truename,u_sex,u_location,u_face,u_intro) values(account,password,now(), 0, ‘a’, name, tname, sex, ‘null’, ‘null’, ‘null’);
    select * from user_tbl;
    end //
    delimiter ;
    call sp1(‘www’,‘32ewew’,‘wan’,‘dongyu’,‘男’);

    3)數據刪除,結果如下:

    – 數據刪除
    drop procedure if exists del;
    – 如果存在就drop
    delimiter //
    – 定義為碰到//才表示語句結束
    create procedure del(id int)
    begin
    delete from Circlemsg_tbl where p_id = id;
    select * from Circlemsg_tbl;
    end //
    delimiter ;
    call del(3);
    – 定義為碰到;表示語句結束
    call del();
    – 定義為碰到;表示語句結束
    4)數據修改,結果如下:

    drop procedure if exists up;
    – 如果存在就drop
    delimiter //
    – 定義為碰到//才表示語句結束
    create procedure up(name varchar(255),psd varchar(255))
    begin
    UPDATE user_tbl SET u_password = psd WHERE u_username = name;
    select * from user_tbl;
    end //
    delimiter ;
    call up(‘wan’,‘11111’);
    – 定義為碰到;表示語句結束
    2.通過ODBC、OLEDB、JDBC或任意其他的途徑,在前端程序(C/S或B/S模式)中調用所實現的后臺存儲過程。
    我使用的是JDBC實現在前端程序調用數據庫后臺存儲過程,代碼過長,放入壓縮包中。(網頁采用的是Jquery架構),網頁整體頁面如下:

  • 數據查詢:(輸入用戶名,點擊查詢按鈕即可查詢到數據庫中該用戶的信息并在頁面顯示出來),結果如下圖:

  • 數據插入操作 插入用戶信息,點擊頁面的添加按鈕,在動態彈出的表單中輸入用戶信息,點擊確認,即可完成添加,添加結果自動返回顯示,操作界面如下圖:

  • 數據刪除操作 點擊每個用戶欄對應的最右邊的刪除鏈接,即可實現對該用戶的刪除操作,刪除完成后自動顯示當前數據庫的狀態結果。如下圖所示:

  • 數據修改操作,點擊每個用戶欄對應的最右邊的修改密碼鏈接,跳轉到修改密碼的頁面,輸入新的密碼,即可實現對該用戶的密碼修改操作,如下圖所示:

  • 跳轉:

    3.在你的案例場景中,分別設計并實現一個由數據插入、數據更新、數據刪除所引發的觸發器(前觸發或后觸發都可以),測試觸發器執行效果。
    –創建記錄微信用戶的表wechat_count,默認為0
    CREATE TABLE wechat_count (
    wechat_count INT(11) DEFAULT 0
    );
    INSERT INTO wechat_count VALUES(0);
    select * from wechat_count;

    1) 數據插入
    –創建簡單觸發器,在向wechat_tbl表INSERT數據時,wechat_count增加
    CREATE TRIGGER trigger_insert
    AFTER INSERT
    ON user_tbl FOR EACH ROW
    UPDATE wechat_count SET wechat_count=wechat_count+1;

    --驗證觸發器,插入一個同學信息,wechat_count應該增加1個

    call sp1(‘weqqw’,‘3121w’,‘anan’,‘pengyuyan’,‘男’);;
    select * from wechat_count;
    結果如下:

    2) 數據更新
    –數據更新
    –創建簡單觸發器,在向wechat_tbl表UPDATA數據時,
    –創建記錄數據更新技術的updata_count
    CREATE TABLE updata_count (
    updata_count INT(11) DEFAULT 0
    );
    INSERT INTO updata_count VALUES(0);
    select * from updata_count;

    CREATE TRIGGER trigger_updata
    AFTER UPDATE
    ON user_tbl FOR EACH ROW
    UPDATE updata_count SET updata_count=updata_count+1;

    –驗證觸發器
    delimiter ;
    call up(‘2wed’,‘111121311’);
    select * from user_tbl;
    select * from updata_count;

    3) 數據刪除
    –數據刪除
    –創建簡單觸發器,在向wechat_tbl表DELETE數據時,wechat_count減少
    CREATE TRIGGER trigger_delete
    AFTER DELETE
    ON user_tbl FOR EACH ROW
    UPDATE wechat_count SET wechat_count=wechat_count-1;
    DELETE FROM user_tbl WHERE u_id=11;
    select * from wechat_count;

    二、 壓力測試與索引實驗(注意提前備份好機器上的關鍵數據,以免因實驗而意外損失)

  • 結合作業#3,針對你的數據庫中的一個表,編寫簡單的數據查詢(查詢語句應包括單個涉及非主屬性等值比較的查詢條件,設該非主屬性為A,具體屬性結合業務背景)和數據插入語句,程序應能在終端或服務器以文件形式記錄每次數據讀寫操作的耗時。
  • 無索引壓力測試實驗:設定該表的數據插入頻率(如100條/秒),至少有1臺以上終端以并發的形式插入數據,運行一段時間使數據達到百萬條級以上,數據規模上限自定。同時使用1臺終端每秒并發執行一次查詢操作,要求查詢條件不包含主碼,且不存在針對屬性A建立的非聚集索引。
  • 有索引壓力測試:清空原有數據,實驗內容同上,但除主鍵索引外,需要針對屬性A建立非聚集索引,重新執行一輪壓力測試。
  • 選做:加大數據插入與查詢頻率,觀察你的服務器和不同設計方案的壓力承受能力。注意控制規模以免導致硬盤工作空間溢出。
  • 分析實驗數據,制作圖表,比較有索引和無索引的情況下,插入時間與查詢時間隨數據量增加的變化情況,以及在相同資源條件下比較有索引和無索引的情況下同一指標隨數據量增加的變化情況,分析導致實驗結果的原因。
    實驗過程如下:
    1)
  • 首先,選取之前建立的數據庫,選擇wechat_tbl表(也就是用戶表)
  • 編寫簡單的查詢語句為:select*from wechat_tbl where wechat_password=‘oqXKaJ’(查詢密碼為oqXKaJ的用戶),其中wechat_password為非主屬性滿足題目要求。
  • 數據插入語句我選擇由java程序實現,設計程序語言讀取記錄每次查詢和插入所需要的時間,并且能夠將結果存入txt文件中。程序運行結果如下圖所示:(代碼已放入壓縮包中)
  • 2)無索引壓力測試實驗:

  • 在代碼中通過Thread.sleep(1000)控制插入頻率和查詢頻率(題目要求為插入頻率100條/秒,查詢頻率為1/秒)

  • 查詢所插入和查詢的表中存在的索引,確定不存在針對wechat_password建立的非聚集索引,查詢結果如下圖所示:

  • 將寫好的java運行一段時間使數據達到百萬條級以上(在java內通過循環實現),數據上限我設的是100萬條,運行寫好的程序,將每秒每插入100條數據的時間以及查詢一次的時間記錄到文本中(文本文件已放入壓縮包),對這10000條數據使用Excel 對每100條數據求平均值,進行擬合得出隨數據增加插入時間變化圖表以及查詢時間變化圖表如下:

  • 3) 有索引壓力測試:

  • 清空原有數據,實驗內容同上,wechat_password建立非聚集索引,重新執行一輪壓力測試,過程如下圖所示:
  • 可見數據量較大時,創建索引的時間也比較長;

    上圖為刪掉增加的100萬條數據;

    重新開始運行程序
    2. 數據上限依然設的是100萬條,運行寫好的程序,將每秒每插入100條數據的時間以及查詢一次的時間記錄到文本中(文本文件已放入壓縮包),對這10000條數據使用Excel 對每100條數據求平均值,進行擬合得出隨數據增加插入時間變化圖表以及查詢時間變化圖表如下:

    4) 分析實驗數據:

  • 有索引和無索引的情況下,插入時間與查詢時間隨數據量增加的變化情況對比圖在上方展示,由此分析:
    無索引的情況下:
    首先,插入時間每插入100條數據,所需要的時間都大致在170ms左右波動,并且隨數據量的增加,由圖所示趨勢線可知在不斷增長。
    其次,數據庫在多于100萬條數據的情況下,查詢時間由開始的1ms,到100萬條數據時的400ms,查詢所需時間隨插入數據量的增加,查詢所需時間呈增長趨勢,大致平均每10萬條數據查詢所需要的時間就要增加40ms。
    有索引的情況下:
    首先,相比無索引的情況,插入數據時間大致在270Ms左右,隨數據量的增加,由圖所示趨勢線可知也在不斷增長。每次查詢的時間大大減少,100萬數據時查詢時間由之前的無索引狀態下的400ms變成現在的1ms左右,其查詢速度顯著提高,并且隨著插入數據的增加,查詢時間并沒有明顯的增加,一直保持在1Ms左右,可見加入索引之后大大提高了查詢的速度。

  • 相同數據量情況下
    經統計插入一百萬條數據無索引一共需要1765578ms,也就是1765.578s,而有索引情況下插入一百萬條數據需要3260311ms,也就是3260.311s,比較發現二者時間差接近兩倍。
    有索引在相同數據量情況下的查詢時間在數據量少時與無索引查詢時間相差不大,但是在數據量大時,產生了較大的差異,無索引查詢時間呈線性增長趨勢,而有索引并無增長趨勢,而控制在一個常數范圍。
    另外,有索引的插入速度在相同數據量情況下,每插入100條數據比無索引慢了大概100ms左右,且隨數據量的增加,差異值一直控制在這個范圍內,沒有明顯增長。

  • 實驗結果分析:
    有上面結果可知,添加索引后使查詢速度增加了,卻使插入速度降低了,索引能讓數據庫查詢數據的速度上升, 而使寫入數據的速度下降,原因很簡單的, 因為平衡樹這個結構必須一直維持在一個正確的狀態, 增刪改數據都會改變平衡樹各節點中的索引數據內容,破壞樹結構, 因此,在每次數據改變時, DBMS必須去重新梳理樹(索引)的結構以確保它的正確,這會帶來不小的性能開銷,也就是為什么索引會給查詢以外的操作帶來副作用的原因。
    對于用到的非聚簇索引,除了聚集索引以外的索引都是非聚集索引,細分一下非聚集索引,分成普通索引,唯一索引,全文索引。非聚集索引和聚集索引一樣, 同樣是采用平衡樹作為索引的數據結構。索引樹結構中各節點的值來自于表中的索引字段, 假如給wechat_name表的wechat_password字段加上索引 ,那么索引就是由wechat_password字段中的值構成,在數據改變時, DBMS需要一直維護索引結構的正確性。如果給表中多個字段加上索引 , 那么就會出現多個獨立的索引結構,每個索引(非聚集索引)互相之間不存在關聯。非聚集索引和聚集索引的區別在于, 通過聚集索引可以查到需要查找的數據, 而通過非聚集索引可以查到記錄對應的主鍵值 , 再使用主鍵的值通過聚集索引查找到需要的數據。
    每次給字段建一個新索引, 字段中的數據就會被復制一份出來, 用于生成索引。 因此,給表添加索引,會增加表的體積,占用磁盤存儲空間。這也就解釋了實驗中添加索引后插入速度降低的原因。
    經過本次實驗,在以后創建表格時,盡量保證將主要的數據都插入之后,再添加索引,避免在添加索引之后進行數據插入,以保證效率最高。
    附錄:(壓力測試java代碼)

  • package testmysql;
    import java.io.File;
    import java.io.FileWriter;
    import java.io.IOException;
    import java.io.Writer;
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.PreparedStatement;
    import java.sql.SQLException;
    import java.util.Date;
    import java.util.Random;

    public class TestMysql {
    static int k;
    public static void main(String[] arg){
    Connection conn;
    PreparedStatement stmt;
    String driver = “com.mysql.jdbc.Driver”;
    String url = “jdbc:mysql://localhost:3306/wechat?useSSL=false&serverTimezone=Asia/Shanghai”;
    String user = “root”;
    String password = null;
    String sql = “insert into wechat_tbl values (?,?,?,?,?,?,?)”;
    String sql2 = “select*from wechat_tbl where wechat_password=‘oqXKaJ’”;
    k=101;
    Boolean result = false;
    File file =new File(“D:\soft\2.txt”);
    try{
    Writer out =new FileWriter(file);
    int count = 0;
    while(!result) {

    try{Class.forName(driver);conn = DriverManager.getConnection(url, user, password);stmt = (PreparedStatement) conn.prepareStatement(sql);Thread.sleep(1000); //設置暫停的時間 1秒count ++ ;System.out.println(new Date() + "--循環執行第" + count + "次");long saa=0;for(int i=0;i<100;i++){stmt.setInt(1, i+k);stmt.setString(2, TestMysql.getRandomString(7));stmt.setString(3, TestMysql.getRandomString(5));if(i%2==0){stmt.setString(4, "boy");}else{stmt.setString(4, "girl");}stmt.setString(5, TestMysql.getRandomString(6));stmt.setString(6, "china");stmt.setString(7, TestMysql.getRandomString(9));long spp = System.currentTimeMillis();stmt.executeUpdate();long sqq = System.currentTimeMillis();saa += sqq-spp;}k=k+101;long midTime = System.currentTimeMillis();stmt = (PreparedStatement) conn.prepareStatement(sql2);stmt.executeQuery();long endTime =System.currentTimeMillis();long usedTime2 = (endTime-midTime); System.out.println(saa+"ms "+usedTime2+"ms");out.write(saa+"ms "+usedTime2+"ms\n");if (count == 10000) {result = true;out.close();break ;}}catch (InterruptedException e) {e.printStackTrace();} catch (ClassNotFoundException e) {// TODO 自動生成的 catch 塊e.printStackTrace();} catch (SQLException e) {// TODO 自動生成的 catch 塊e.printStackTrace();}}}catch(IOException e){e.printStackTrace();}} public static String getRandomString(int length) {Random random = new Random();StringBuffer sb = new StringBuffer();for (int i = 0; i < length; i++) {int number = random.nextInt(3);long result = 0;switch (number) {case 0:result = Math.round(Math.random() * 25 + 65);sb.append(String.valueOf((char) result));break;case 1:result = Math.round(Math.random() * 25 + 97);sb.append(String.valueOf((char) result));break;case 2:sb.append(String.valueOf(new Random().nextInt(10)));break;}}return sb.toString(); }

    總結

    以上是生活随笔為你收集整理的数据库压力测试的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。