mysql數據庫優化(四)-項目實戰

在flask項目中,防止隨着時間的流逝,數據庫數據越來越多,導致接口訪問數據庫速度變慢。所以自己填充數據進行測試及 mysql優化

1.插入數據:

通過腳本,使用多進程,每100次提交數據

import multiprocessing
import time

from flask import Flask
from flask_sqlalchemy import SQLAlchemy

HOST = '127.0.0.1'
USER = "root"
PASSWD = ""
DB = "fwss_dev"
CHARTSET = "utf8"

app = Flask(__name__, instance_relative_config=True)
# 鏈接數據庫路徑
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://%s:%[email protected]:3306/%s?charset=%s' % (USER, PASSWD, DB, CHARTSET)
# 如果設置成 True (默認情況),Flask-SQLAlchemy 將會追蹤對象的修改並且發送信號。這需要額外的內存, 如果不必要的可以禁用它。
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
# 如果設置成 True,SQLAlchemy 將會記錄所有 發到標準輸出(stderr)的語句,這對調試很有幫助。
app.config['SQLALCHEMY_ECHO'] = False
# 數據庫連接池的大小。默認是數據庫引擎的默認值 (通常是 5)。
app.config['SQLALCHEMY_POOL_SIZE'] = 6
db = SQLAlchemy(app)


def insert(count):
    start = time.time()
    for item in range(50000):
        # time1 = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(time_one))
        print(count)
        for it in range(100):
            db.session.execute(
                f"""INSERT INTO order_bang (creator_id,redenvelope,status) VALUES
                                       ({count},12,0,'需要')"""
                # f"INSERT INTO account_realauth (uid,`status`) VALUES({count},2)"
            )
        count += 1
        db.session.commit()
    print((time.time() - start) / 60)


if __name__ == '__main__':
    with app.app_context():
        multiprocessing.Process(target=insert, args=(273256,)).start()
        multiprocessing.Process(target=insert, args=(10273256,)).start()
        multiprocessing.Process(target=insert, args=(20273256,)).start()
        multiprocessing.Process(target=insert, args=(30273256,)).start()

以上只是展示 部分插入數據庫的腳本,總共插入數據量如下: 用戶表(account_user)110萬用戶,實名認證表(account_realauth)20萬用戶,某訂單表(order_bang)2023萬條。相關表結構如下:

CREATE TABLE `order_bang` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `creator_id` int(11) NOT NULL,
  `status` tinyint(4) DEFAULT NULL,
  `create_time` datetime DEFAULT NULL,
  `province_id` char(6) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `city_id` char(4) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
........
PRIMARY KEY (`id`), KEY `ix_order_bang_province_id` (`province_id`), KEY `ix_order_bang_status` (`status`), KEY `bang_addr_index` (`province_id`,`city_id`), KEY `ix_order_bang_create_time` (`create_time`), KEY `ix_order_bang_creator_id` (`creator_id`) )

 

 

2.在flask中記錄查詢較慢的sql語句及相關信息

本人設置最長查詢時間爲0.1秒便記錄

相關 方法在:項目中記錄影響性能的緩慢數據庫查詢

 

3.關閉mysql緩存功能 

         查看緩存是否開啓,

輸入命令:show variables like '%cache%';       query_cache_type值爲OFF表示關閉

           

關閉方式輸入如下:

one.

set global query_cache_type=0
set global query_cache_size=0

 

two.

查詢中添加:  Select sql_no_cache count(*) from account_user; 不緩存

 

4.查看相關結果,並進行優化

一:

時間耗時3.32秒。

 分析得知:

where子句條件時uid進行篩選,而索引用的是 id。

解決方法:

第一種:在 uid上添加索引。

分析得知:

查詢使用uid的索引,耗時0.002秒。

第二種:對於客戶端不需要表中全部字段的情況,在查詢時最好選擇具體的字段,而不是直接 select  *  from table;這樣 可以減少網絡帶寬

在sqlalchemy中爲如下(直接使用類方法,及查詢具體字段,而不是返回一個對象)

class RealAuth(DB.Model):
    @classmethod
def get_success_realname(cls, uid):
db_result = DB.session.query(cls.real_name).filter(
and_(cls.uid == uid, cls.status == RealAuthStatus.SUCCESS)).order_by(
cls.id.desc()).limit(1).first()

 

總結:

錯誤原因:由於沒有對where子句條件使用索引,導致查詢過慢

經驗教訓:添加索引

 

 二:在查訂單時, 接口直接 無響應

sql語句如下:

 

索引如下:

city字段類型是 char類型

 

通過 explain查看本條sql,city_id傳的值是int類型:

索引使用的是 create_time。

把city_id改爲數據庫中設定的 str 類型,再次查看

總結:

錯誤原因:導致此接口查詢無響應的原因是 在 大量數據的情況下,沒有規範 書寫 sql查詢的數據類型,導致 無法使用正確的索引,而導致此問題

經驗教訓:在開發中,在sql執行之前,一定要手動的把 查詢條件的值的類型和設計表時的類型相對應,否則可能導致 數據庫無法使用此索引,而出錯。

 

待更新;

發佈了92 篇原創文章 · 獲贊 2 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章