zoukankan      html  css  js  c++  java
  • mysql优化(一)

    数据库设计

    什么是数据库范式

    • 为了建立冗余较小、结构合理的数据库,设计数据库时必须遵循一定的规则。在关系型数据库中这种规则就称为范式。范式是符合某一种设计要求的总结。要想设计一个结构合理的关系型数据库,必须满足一定的范式。

    数据库三大范式

    第一范式:1NF是对属性的原子性约束,要求属性(列)具有原子性,不可再分解;(只要是关系型数据库都满足1NF)
    第二范式:2NF是对记录的惟一性约束,表中的记录是唯一的, 就满足2NF, 通常我们设计一个主键来实现,主键不能包含业务逻辑。
    第三范式:3NF是对字段冗余性的约束,它要求字段没有冗余。 没有冗余的数据库设计可以做到。

    分表分库

    • 垂直拆分
      垂 直 拆 分 就 是 要 把 表 按 模 块 划 分 到 不 同 数 据 库 表 中(当 然 原 则 还 是 不 破 坏 第 三 范 式),这 种 拆 分在 大 型 网 站 的 演 变 过 程 中 是 很 常 见 的。当 一 个 网 站 还 在 很 小 的 时 候,只 有 小 量 的 人 来 开 发 和 维护,各 模 块 和 表 都 在 一 起,当 网 站 不 断 丰 富 和 壮 大 的 时 候,也 会 变 成 多 个 子 系 统 来 支 撑,这 时 就 有 按 模 块 和 功 能 把 表 划 分 出 来 的 需 求。其 实,相 对 于 垂 直 切 分 更 进 一 步 的 是 服 务 化 改 造,说 得 简 单 就是 要 把 原 来 强 耦 合 的 系 统 拆 分 成 多 个 弱 耦 合 的 服 务,通 过 服 务 间 的 调 用 来 满 足 业 务 需 求 看,因 此 表 拆 出 来 后 要 通 过 服 务 的 形 式 暴 露 出 去,而 不 是 直 接 调 用 不 同 模 块 的 表 ,淘 宝 在 架 构 不 断 演 变 过程, 最 重 要 的 一 环 就 是 服 务 化 改 造 ,把 用 户 、交 易 、店 铺、宝 贝 这 些 核 心 的 概 念 抽 取 成 独 立 的 服务, 也 非 常 有 利 于 进 行 局 部 的 优 化 和 治 理,保 障 核 心 模 块 的 稳 定 性
      垂 直 拆 分 用 于 分 布 式 场 景。
    • 水平拆分
      谈 到 垂 直 切 分 只 是 把 表 按 模 块 划 分 到 不 同 数 据 库 ,但 没 有 解决 单 表大 数 据 量 的 问 题,而 水 平 切 分 就 是 要 把 一 个 表 按 照 某 种 规 则 把 数 据 划 分 到 不 同 表 或 数据 库 里 。例 如 像 计 费 系 统,通 过 按 时 间 来 划 分 表 就 比 较 合 适,因 为 系 统 都 是 处 理 某 一 时 间 段 的 数 据。而 像S aaS应 用,通 过 按 用 户 维 度 来 划 分 数 据 比 较 合 适,因 为 用 户 与 用 户 之 间 的 隔 离 的,一 般 不 存 在 处 理 多 个 用 户 数 据 的 情 况,简 单 的 按 user_id范 围 来 水 平 切 分

    通 俗 理 解 :水 平 拆 分 行,行 数 据 拆 分 到 不 同 表 中, 垂 直 拆 分 列,表 数 据 拆 分 到 不 同 表 中

    SQL优化

    MySQL如何优化
    表的设计合理化(符合3NF)
    添加适当索引(index) [四种: 普通索引、主键索引、唯一索引unique、全文索引]
    SQL语句优化
    分表技术(水平分割、垂直分割)
    读写[写: update/delete/add]分离
    存储过程 [模块化编程,可以提高速度]
    对mysql配置优化 [配置最大并发数my.ini, 调整缓存大小 ]
    mysql服务器硬件升级
    定时的去清除不需要的数据,定时进行碎片整理(MyISAM)
    

    show status
    使用show status使用show status查看MySQL服务器状态信息
    常用命令
    --mysql数据库启动了多少时间
    show status like 'uptime';
    show stauts like 'com_select'
    show stauts like 'com_insert' ...类推 update delete(显示数据库的查询,更新,添加,删除的次数)
    show [session | global] status like .... 如果你不写 [session|global] 默认是session 会话,指取出当前窗口的执行,如果你想看所有(从mysql 启动到现在,则应该 global)
    //显示到mysql数据库的连接数
    show status like 'connections ';
    //显示慢查询次数
    show status like 'slow_queries';

    什么是慢查询

    MySQL默认10秒内没有响应SQL结果,则为慢查询
    可以去修改MySQL慢查询默认时间

    如何修改慢查询

    --查询慢查询时间
    show variables like 'long_query_time';
    --修改慢查询时间
    set long_query_time=1; ---但是重启mysql之后,long_query_time依然是my.ini中的值

    • 初始化测试数据
    • 创建表结构
    /*部门表*/
    CREATE TABLE dept( 
    deptno MEDIUMINT   UNSIGNED  NOT NULL  DEFAULT 0,  /*编号*/
    dname VARCHAR(20)  NOT NULL  DEFAULT "", /*名称*/
    loc VARCHAR(13) NOT NULL DEFAULT "" /*地点*/
    ) ENGINE=MyISAM DEFAULT CHARSET=utf8 ;
    /*员工表*/
    CREATE TABLE emp
    (empno  MEDIUMINT UNSIGNED  NOT NULL  DEFAULT 0, /*编号*/
    ename VARCHAR(20) NOT NULL DEFAULT "", /*名字*/
    job VARCHAR(9) NOT NULL DEFAULT "",/*工作*/
    mgr MEDIUMINT UNSIGNED NOT NULL DEFAULT 0,/*上级编号*/
    hiredate DATE NOT NULL,/*入职时间*/
    sal DECIMAL(7,2)  NOT NULL,/*薪水*/
    comm DECIMAL(7,2) NOT NULL,/*红利*/
    deptno MEDIUMINT UNSIGNED NOT NULL DEFAULT 0 /*部门编号*/
    )ENGINE=MyISAM DEFAULT CHARSET=utf8 ;
    
    
    
    /*薪水*/
    CREATE TABLE salgrade
    (
    grade MEDIUMINT UNSIGNED NOT NULL DEFAULT 0,
    losal DECIMAL(17,2)  NOT NULL,
    hisal DECIMAL(17,2)  NOT NULL
    )ENGINE=MyISAM DEFAULT CHARSET=utf8;
    
    /*测试数据*/
    
    INSERT INTO salgrade VALUES (1,700,1200);
    INSERT INTO salgrade VALUES (2,1201,1400);
    INSERT INTO salgrade VALUES (3,1401,2000);
    INSERT INTO salgrade VALUES (4,2001,3000);
    INSERT INTO salgrade VALUES (5,3001,9999);
    

    创建函数

    create function rand_string(n INT) 
    returns varchar(255) #该函数会返回一个字符串
    begin 
    #chars_str定义一个变量 chars_str,类型是 varchar(100),默认值'abcdefghijklmnopqrstuvwxyzABCDEFJHIJKLMNOPQRSTUVWXYZ';
     declare chars_str varchar(100) default
       'abcdefghijklmnopqrstuvwxyzABCDEFJHIJKLMNOPQRSTUVWXYZ';
     declare return_str varchar(255) default '';
     declare i int default 0;
     while i < n do 
       set return_str =concat(return_str,substring(chars_str,floor(1+rand()*52),1));
       set i = i + 1;
       end while;
      return return_str;
      end 
    
    create FUNCTION rand_num()
    RETURNS int(5)
    BEGIN
     DECLARE i int default 0;
     set i =floor(10+RAND()*500);
     return i;
    END
    
    

    创建存储过程

    delimiter $$
    create procedure insert_emp(in start int(10),in max_num int(10))
    begin
    declare i int default 0; 
    #set autocommit =0 把autocommit设置成0
     set autocommit = 0;  
     repeat
     set i = i + 1;
     insert into emp values ((start+i) ,rand_string(6),'SALESMAN',0001,curdate(),2000,400,rand_num());
      until i = max_num
     end repeat;
       commit;
     end $$
    执行存储过程
    call insert_emp (100001,40000000);  
    

    如何将慢查询定位到日志中

    在默认情况下,我们的mysql不会记录慢查询,需要在启动mysql时候,指定记录慢查询才可以
    binmysqld.exe --safe-mode --slow-query-log [mysql5.5 可以在my.ini指定](安全模式启动,数据库将操作写入日志,以备恢复)
    binmysqld.exe –log-slow-queries=d:/abc.log [低版本mysql5.0可以在my.ini指定]
    先关闭mysql,再启动, 如果启用了慢查询日志,默认把这个文件放在
    my.ini 文件中记录的位置

    Path to the database root

    datadir=" C:/ProgramData/MySQL/MySQL Server 5.5/Data/"

  • 相关阅读:
    八皇后之回溯算法
    手撕堆排序 优先级队列的实现方式
    扩展1000!(n!)的尾数零的个数
    #12. 整数转罗马数字 穷举法
    #11 盛最多水的容器
    Sql Server 复制数据库
    常见dos命令行
    JSP页面中,EL表达式获取根路径。
    maven springTest结合junit单元测试
    【Java异常】Exception in thread“main” java util ConcurrentModificationException的解决方案
  • 原文地址:https://www.cnblogs.com/Libbo/p/11531332.html
Copyright © 2011-2022 走看看