Database 性能優化主意事項

1. 查找執行慢的SQL

Mysql查詢當前執行的sql

SELECT * FROM information schema.PROCESSLIST where info is not null;

Time列是sql持續的時間,單位是秒,越少越好,至少會有一條記錄,就是當前的監控sql。

Mysql查詢未提交事務中的歷史SQL

SELECT
	ps.id 'PROCESS ID',
	ps. USER,
	ps. HOST,
	esh.EVENT_ID,
	trx.trx_started,
	esh.event_name 'EVENT NAME',
	esh.sql_text 'SQL',
	ps.time
FROM
	performance_schema.events_statements_history esh
JOIN performance_schema.threads th ON esh.thread_id = th.thread_id
JOIN information_schema.PROCESSLIST ps ON ps.id = th.processlist_id
LEFT JOIN information_schema.innodb_trx trx ON trx.trx_mysql_thread_id = ps.id
WHERE
	ps.time > 60
AND trx.trx_id IS NOT NULL
AND ps. USER != 'SYSTEM_USER'
ORDER BY
	esh.EVENT_ID;

當發現有鎖長期存在,影響別的事務,就需要本腳本

SQLServer查詢執行過的SQL

SELECT top 10 
  qs.total_worker_time / qs.execution_count / 1000 耗時
,st.text as sql_statement
,qs.creation_time as plan_last_compiled
,qs.last_execution_time as plan_last_executed
,qs.execution_count as plan_executed_count
,qp.query_plan
FROM sys.dm_exec_query_stats qs
CROSS APPLY sys.dm_exec_sql_text(qs.plan_handle) st
CROSS APPLY sys.dm_exec_query_plan(qs.plan_handle) qp
order by plan_last_executed desc

沒有準‘實時’的抓取功能,只能是‘僞實時’

2. SQL 事務、鎖分析

select * from information_schema.`PROCESSLIST` where info is not NULL;
select * from information_schema.INNODB_TRX;  -- 顯示掛起的事務
select * from information_schema.INNODB_LOCK_WAITS; -- 鎖等待
select * from information_schema.INNODB_LOCKS; -- 正在使用的鎖
SELECT * FROM information_schema.INNODB_TRX;
kill  trx_mysql_thread_id;

3. 數據表信息收集

Mysql 單表信息收集,表的記錄數,及佔空間情況

SELECT TABLE_SCHEMA,TABLE_NAME,round((DATA_LENGTH+INDEX_LENGTH)/1024/1024/1024,3) `size(GB)`,TABLE_ROWS FROM information_schema.tables
where table_name = 'vote_record' 

SQLServer 單表信息收集

exec sp_spaceused '表名'

4.性能主意點

a. 使用連接Join來代替子查詢
查詢沒有子表信息的主表記錄

select * from employee where id not in (select empId from employeeInfo);
// 優化
select * 
from employee e left join employeeInfo eInfo ON e.id = eInfo,empId
where eInfo.empId is null

b. 使用索引的注意點
最好在相同類型的字段間進行比較

在建有所有的字段上儘量不要使用函數操作

select * from order where year(orderDate) < 2001;
select * from order where orderDate < '2001-01-1';

慎用like “%abc%” 這是以犧牲性能爲代價的

索引是可以多字段

 Create index ix_date_emp on t_工作日誌表 (date, empid);
Create index ix_emp_date on t_工作日誌表 (empid, date);
Create index ix_date on t_工作日誌表 (date);
Create index ix_emp on t_工作日誌表 (empid);

c. 使用冗餘字段
記錄表,實例表等表結構,可以違反3NF,增加冗餘字段,比如保留操作人姓名,部門名稱,訂單總價等等。方便查詢

d. 減少一個SQL中JOIN 的個數
https://chenrenfei.github.io/sqltoy/#/

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