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/#/

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