优化_优化模型 - CSDN
精华内容
参与话题
  • Matlab数学建模(五):优化模型之标准模型

    千次阅读 多人点赞 2018-11-18 20:34:38
    (1)了解最优化模型。 (2)掌握线性规划的优化求解。 (3)掌握整数规划的优化求解。 (4)了解Matlab的图形化应用。 二、实例演练  1、谈谈你对最优化模型的了解。  最优化模型是数学建模大赛中最常见的...

    一、学习目标

    (1)了解最优化模型。

    (2)掌握线性规划的优化求解。

    (3)掌握整数规划的优化求解。

    (4)了解Matlab的图形化应用。

    二、实例演练

         1、谈谈你对最优化模型的了解。

            最优化模型是数学建模大赛中最常见的问题类型之一。一般说来,凡是寻求最大、最小、最远、最近、最经济、最丰富、最高效、最耗时的目标,都可以划入优化问题的范畴。MATLAB 优化工具箱和全局优化工具箱对多个优化问题提供了完整的解决方案,前者涵盖了线性规划、混合整型线性规划、二次规划、非线性优化、非线性最小二乘的求解器,后者囊括了全局搜索、多初始点、模式搜索、遗传算法等求解算法。

           最优化即在一定的条件下,寻求使目标最小(大)的设计参数或决策。在优化问题中有两个关键对象:目标函数约束条件。哈哈哈,这让笔者想起来高中学到的线性规划,其实,本节谈到的最优化模型跟高中的线性规划还真有点像。不过,高中的线性规划问题约束条件很少,一般是通过作图法来求解。本节的最优化模型约束条件一般比高中的线性规划多很多,并且我们要通过写代码去求解,而不是作图。常规优化问题,其数学表达可以描述为:

    其中x 为长度n的决策变量向量,f(x) 为目标函数,G(x) 为约束函数。

    以上数学表达式看不明白也没关系,因为下面我们会通过两个具体的例子去讲解分析。

    求解目标函数的最小(大)值,一个高效而精确的解决方案不仅取决于约束条件和变量数量,更取决于目标函数和约束函数的特性。明确优化类型是确认优化方案的前提,让我们看一下这些特性如何划分:

    常见的目标函数有:

    线性规划:被广泛的应用于变量之间可线性表示的财务、能源、运营研究等现代管理领域中。

    混合整数线性规划:扩展了线性规划问题,增加了最优解中部分或全部变量必须是整数的约束。例如,如果一个变量代表要认购的股票数量,则只应取整数值。同样,如果一个变量代表发电机的开/关状态,则只应取二进制值(0 或 1)。

    二次规划:目标函数或约束函数为多元二次函数。此优化应用于财务金融中投资组合优化、发电厂发电优化、工程中设计优化等领域。

    最小二乘:分为线性和非线性,通过最小化误差的平方和寻找变量的最优函数匹配。非线性最小二乘优化还可用于曲线拟合。

     

    对 MATLAB 提供的各类优化问题的算法,我们称之为求解器(Solver)。根据其求解目标,被分为四大组:

    • 极小值优化组:找到目标函数出发点 x0 附近的局部极小值

    • 多目标优化组:找到最小化一组函数的最大值或指定的值

    • 方程求解组:找到非线性方程 f(x) = 0 出发点 x0 附近的解

    • 最小二乘法(曲线拟合)组:最小化平方和

    仅优化工具箱就提供了近 20 种求解器,面对如此繁多的选项,用户往往一头雾水。幸好,MATLAB 提供了简单明了的参考工具 —— 优化决策表。可谓一表在手,优化不愁:

    上表中*表示算法由全局工具箱提供。

    我的天呀,你是不是已经被上面的内容吓傻了。看不太懂?没关系。我们现在只需知道有那么一回事即可,不必苦恼。等遇到相应的问题时我们再去结合具体的例子去深入学习和理解。

        2、已知目标函数和约束条件如下,试求解目标函数的最小值。

                                 

           初一看,HPS、PP、EP、P1、I1,……等等,这些是什么东东?别紧张,它们只是变量,把它们当成x,y,z这种常见的变量去看待即可。我数了一下,约束函数中共有19条数学表达式,涉及16个变量。是挺难搞的,用高中的作图法怕是解决不了。别怕,我们有Matlab,通过代码去搞定它。

           好,现在我们开始一步步去求解它。

    a. 首先,根据题目确认这是一个线性规划问题。而线性规划的通用数学表达式和MATLAB标准形式为:

    这个标准形式很重要,上面的A,b,Aeq,beq,lb,ub我们后面要用到。

    b. 对于线性规划的优化求解步骤(也适用于其他优化方案),建议如下:

        1 ) 选择优化求解器

        2 ) 将所有变量合并为一个向量

        3 ) 创建边界约束(lb,ub)

        4 ) 创建线性不等式约束(A,b)

        5 ) 创建线性等式约束(Aeq,beq)

        6 ) 创建目标函数

        7 ) 优化问题求解

        8 ) 结果检验

    上面的求解步骤非常重要,我们的代码整体框架跟求解步骤差不多。

    现在我们按照上面的求解步骤去求解:

    (1)选择优化求解器。

    这道题目是这是一个线性规划问题。求解线性规划问题,我们一般选用linprog。linprog在写代码将要写完才需用到。在第一步我们只需要知道一个线性规划问题,代码按照求解线性规划问题去写即可。

    (2)将所有变量合并为一个向量。

    目标函数和约束条件中共有HPS、PP、EP、P1、I1等16个变量,我们需要将其合并为一个向量。除了合并为一个向量外,我们还将每个变量依次分别赋值1,2,3,4,……16。

    %% 将所有变量合并为一个向量,共16个变量
    variables = {'I1','I2','HE1','HE2','LE1','LE2','C','BF1','BF2','HPS','MPS','LPS','P1','P2','PP','EP'}
    N = length(variables)
    for v = 1:N
        eval([variables{v},'=',num2str(v),';'])
    end

    (3)创建边界约束(lb,ub)

    lb是指low boundary,即最低边界。ub是指up boundary,即最高边界。在这一步中,我们需要把约束条件里的不等式(该不等式只含单个变量,如2500<=P1<=6250,3000<=P2<=9000)找出来,并根据它们的上下边界写代码。

    %% 设置上下限约束(lb<=x<=ub)
    % 设置下限约束,即lb<=x
    lb = zeros(size(variables)); % 1x16的矩阵,每个数都是0
    lb([P1,P2,MPS,LPS]) = [2500,3000,271536,100623];
    % 设置上限约束,即x<=ub
    ub = Inf(size(variables)); % 1想6的矩阵,每个数都是无穷大
    ub([P1,P2,I1,I2,C,LE2])= [6250,9000,192000,244000,62000,142000];

    (4)创建线性不等式约束(A,b)。

    在这一步需要将约束条件里的不等式(该不等式含两个或两个以上变量)找出来,并根据它们的上下边界写代码。

    %% 创建线性不等式约束(A*x<=b)
    A = zeros(3,16); % 3x16的矩阵,每个数均为0,为什么是3x16,因为约束条件有3个不等式
    % 由不等式I1-HE1<=132000得到下面一行代码
    A(1,I1)=1; A(1,HE1)=-1; b(1) = 132000;
    % 由不等式-EP-PP<=12000得到下面一行代码
    A(2,EP)=-1; A(2,PP)=-1; b(2) = -12000;
    % 由不等式-P1-P2-PP<=-24550得到下面一行代码
    A(3,[P1,P2,PP])=[-1,-1,-1];b(3)=-24550;

    (5)创建线性等式约束(Aeq,beq)。

    在这一步需要把约束条件中的等式找出来,并通过移项,让等式的右边为0。

    %% 创建线性等式约束(Aeq*x=beq)
    Aeq=zeros(8,16);beq=zeros(8,1) % 约束条件中共有8个等式
    % 把等式I2=LE2+HE2转化为LE2+HE2-I2=0后,得到下面一行代码
    Aeq(1,[LE2,HE2,I2])=[1,1,-1];
    Aeq(2,[LE1,LE2,BF2,LPS])=[1,1,1,-1];
    Aeq(3,[I1,I2,BF1,HPS])=[1,1,1,-1];
    Aeq(4,[C,MPS,LPS,HPS])=[1,1,1,-1];
    Aeq(5,[LE1,HE1,C,I1])=[1,1,1,-1];
    Aeq(6,[HE1,HE2,BF1,BF2,MPS])=[1,1,1,-1,-1];
    Aeq(7,[HE1,LE1,C,P1,I1])=[1267.8,1251.4,192,3413,-1359.8];
    Aeq(8,[HE2,LE2,P2,I2])=[1267.8,1251.4,3413,-1359.8];

    (6)创建目标函数。

    %% 创建目标函数
    f = zeros(size(variables));
    % 由目标函数0.002614HPS+0.0239PP+0.009825EP
    f([HPS,PP,EP]) = [0.002614,0.0239,0.009825];

    (7) 求解问题

    %% 由linprog实现线性规划问题求解
    options = optimoptions('linprog','Algorithm','dual-simplex');
    % 将前面已经确定的各个参数传入linprog()中
    [x, fval] = linprog(f,A,b,Aeq,beq,lb,ub,options);
    for d=1:N
        fprintf('%12.2f\t%s\n',x(d),variables{d})
    end

    fprintf函数是将求解后每个变量的打印出来。

    求解结果如下:

    下面把完整的源代码贴上:

    clc,clear,close all
    %% 选择优化求解器,线性规划求解可由linprog实现
    
    %% 将所有变量合并为一个向量,共16个变量
    variables = {'I1','I2','HE1','HE2','LE1','LE2','C','BF1','BF2','HPS','MPS','LPS','P1','P2','PP','EP'}
    N = length(variables)
    for v = 1:N
        eval([variables{v},'=',num2str(v),';'])
    end
    
    %% 设置上下限约束(lb<=x<=ub)
    % 设置下限约束,即lb<=x
    lb = zeros(size(variables)); % 1x16的矩阵,每个数都是0
    lb([P1,P2,MPS,LPS]) = [2500,3000,271536,100623];
    % 设置上限约束,即x<=ub
    ub = Inf(size(variables)); % 1想6的矩阵,每个数都是无穷大
    ub([P1,P2,I1,I2,C,LE2])= [6250,9000,192000,244000,62000,142000];
    
    %% 创建线性不等式约束(A*x<=b)
    A = zeros(3,16); % 3x16的矩阵,每个数均为0,为什么是3x16,因为约束条件有3个不等式
    % 由不等式I1-HE1<=132000得到下面一行代码
    A(1,I1)=1; A(1,HE1)=-1; b(1) = 132000;
    % 由不等式-EP-PP<=12000得到下面一行代码
    A(2,EP)=-1; A(2,PP)=-1; b(2) = -12000;
    % 由不等式-P1-P2-PP<=-24550得到下面一行代码
    A(3,[P1,P2,PP])=[-1,-1,-1];b(3)=-24550;
    
    %% 创建线性等式约束(Aeq*x=beq)
    Aeq=zeros(8,16);beq=zeros(8,1) % 约束条件中共有8个等式
    % 把等式I2=LE2+HE2转化为LE2+HE2-I2=0后,得到下面一行代码
    Aeq(1,[LE2,HE2,I2])=[1,1,-1];
    Aeq(2,[LE1,LE2,BF2,LPS])=[1,1,1,-1];
    Aeq(3,[I1,I2,BF1,HPS])=[1,1,1,-1];
    Aeq(4,[C,MPS,LPS,HPS])=[1,1,1,-1];
    Aeq(5,[LE1,HE1,C,I1])=[1,1,1,-1];
    Aeq(6,[HE1,HE2,BF1,BF2,MPS])=[1,1,1,-1,-1];
    Aeq(7,[HE1,LE1,C,P1,I1])=[1267.8,1251.4,192,3413,-1359.8];
    Aeq(8,[HE2,LE2,P2,I2])=[1267.8,1251.4,3413,-1359.8];
    
    %% 创建目标函数
    f = zeros(size(variables));
    % 由目标函数0.002614HPS+0.0239PP+0.009825EP
    f([HPS,PP,EP]) = [0.002614,0.0239,0.009825];
    
    %% 由linprog实现线性规划问题求解
    options = optimoptions('linprog','Algorithm','dual-simplex');
    % 将前面已经确定的各个参数传入linprog()中
    [x, fval] = linprog(f,A,b,Aeq,beq,lb,ub,options);
    for d=1:N
        fprintf('%12.2f\t%s\n',x(d),variables{d})
    end

      3、下面是一个整数规划问题,已知目标函数和约束条件如下,求解目标函数的最大值。

                                          

         求解最大值问题和求解最小值问题本质上是一致的,求解最大值也可以转换为求解最小值。

    例如:本题要求解z=3*x1-2*x2+5*x3的最大值,也就是要求解y=-3*x1+2*x2-5*x3的最小值。求解线性规划最小值问题我们在上面已经学过。本题还有一个比较特殊的问题是,约束条件中的三个变量均为整数,而且是0或1,这也是所谓的0-1规划问题。

    求解整值问题要用到专门的求解器 intlinprog。

    clc,clear,close all
    % 求z=3*x1 - 2*x2 + 5*x3的最大值转化为求y=-3*x1 + 2*x2 - 5*x3的最小值。
    f = [-3;2;-5]; % 创建目标函数
    intcon=[1,2,3];
    A=[1 2 -1; 1 4 1; 1 1 0; 0 4 1]; % 四个不等式中的变量系数
    b=[2;4;3;6]; % 约束条件中不等式右边的常数
    lb=[0,0,0]; % x1,x2,x3=0
    ub=[1,1,1]; % x1,x2,x3=1
    Aeq=[0,0,0];
    beq=0;
    x=intlinprog(f,intcon,A,b,Aeq,beq,lb,ub)

    我想提一下intcon=[1,2,3]这句代码是怎么回事。

    下面我举一个简单的例子来说明intcon的用法。

    X=[x1,x2,x3,x4,x5,x6],其中x2, x3, x6只能取整数
    intcon = [2,3,6]
    如果所有变量都只能取整数,则:intcon = [1,2,3,4,5,6]; 比较方便的写法是:intcon = 1:6
    如果只有x4取整数,则:intcon = 4;就是约束整形变量

    在本题中,除了x1,x2,x3=0或1外,没有其它的等式了。故Aeq=[0,0,0];beq=0;

     4、图形化应用

    在数学建模竞赛中,我们一般通过代码来进行求解问题,图形化应用可以用来检验结果是否正确。

    MATLAB 在数据分析领域如此受欢迎,除了其提供丰富的内置算法集,还有各类友好的应用界面。在优化工具箱中,也有这么一个强大的工具—— Optimization App,可以在 MATLAB Apps 窗口或者运行 optmitool 命令打开。它是一个交互式的图形化应用工具,无需手写代码,直接在图形界面中设置各类求解器、配置目标函数、约束条件,即可运行优化算法并使中间结果和最终结果可视化。

    在 Optimization App 中,只需点击菜单栏中的 File > Generate Code,即可将 App 中的各项设置自动生成 MATLAB 代码,用户可实现算法的复用和二次开发。

    展开全文
  • 必装软件 yum -y install gcc glibc gcc-c++ make ... yum -y install setuptool ntsysv system-config-securitylevel-tui NetworkMana...

    最小化安装centos后必要的优化

    1、配置网络及更改计算机名

    改计算机名

    hostnamectl set-hostname pokes

    配置网络

    vi /etc/sysconfig/network-scripts/ifcfg-ens33

    网络配置文件内容编辑如下(有注释的是必须改的):

    TYPE="Ethernet"
    BOOTPROTO="static"    #静态
    DEFROUTE="yes"
    PEERDNS="yes"
    PEERROUTES="yes"
    IPV4_FAILURE_FATAL="no"
    IPV6INIT="yes"
    IPV6_AUTOCONF="yes"
    IPV6_DEFROUTE="yes"
    IPV6_PEERDNS="yes"
    IPV6_PEERROUTES="yes"
    IPV6_FAILURE_FATAL="no"
    NAME="eno16777736"
    UUID="0e6ca219-0d2e-4000-8f17-bf7424e46595"
    DEVICE="eno16777736"
    ONBOOT="yes"        #开机开启网卡
    IPADDR=192.168.255.101
    GATEWAY=192.168.255.2
    NETMASK=255.255.255.0
    DNS=114.114.114.114

    2、更改系统源

     

    首先备份源 /ect/yum.repos.d/CentOS-Base.repo,在安装之前我们先必须安装wget

    yum -y install wget yum-utils epel-release
    mv  /etc/yum.repos.d/CentOS-Base.repo  /etc/yum.repos.d/CentOS-Base.repo.bak

    替换为阿里源

    wget -O  /etc/yum.repos.d/CentOS-Base.repo  http://mirrors.aliyun.com/repo/Centos-7.repo
    wget -O  /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo

    或者

    curl -o /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
    curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/CentOS-7.repo

    如果你需要使用docker

    yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

    清楚缓存、生成新缓存

    yum clean all && yum makecache

    3、更新系统

    yum -y upgrade

    升级所有包,不改变软件设置和系统设置,系统版本升级,内核不改变 (不变内核和设置,升级包和系统版本)

    不建议使用update 

    yum -y update

    升级所有包,改变软件设置和系统设置,系统版本内核都升级

    详细请看这里:https://blog.csdn.net/weixin_34415923/article/details/92598179

    4、安装常用的软件

    yum -y install gcc
    yum -y install glibc 
    yum -y install gcc-c++ 
    yum -y install make 
    yum -y install cmake
    yum -y install net-tools
    yum -y install screen
    yum -y install vim
    yum -y install lrzsz
    yum -y install tree
    yum -y install dos2unix
    yum -y install lsof
    yum -y install tcpdump
    yum -y install bash-completion
    yum -y install wget
    yum -y install ntp
    yum -y install setuptool
    yum -y install psmisc
    yum -y install openssl
    yum -y install openssl-devel
    yum -y install bind-utils
    yum -y install traceroute

    一键安装

    yum -y install gcc glibc gcc-c++ make cmake net-tools screen vim lrzsz tree dos2unix lsof tcpdump bash-completion wget ntp setuptool psmisc openssl openssl-devel bind-utils traceroute
    • gcc  glibc  gcc-c++  make cmake  编译器,编译安装的时候会用到
    • net-tools           #Linux内核中配置网络功能的工具
    • screen              #用于命令行终端切换
    • vim                   #编辑器
    • lrzsz                 #拖动上传,sz下载
    • tree                  #树形目录
    • dos2unix          #Windows格式文件转换为Unix、Linux格式的实用命令
    • lsof                  #列出当前系统打开文件的工具
    • tcpdump          #抓包工具
    • bash-completion     #自动补全功能增强
    • wget                 #文件下载
    • ntp                    #同步网络事件
    • psmisc              #帮助管理/proc目录的程序
    • openssl    openssl-devel         #web安全通信的基石,没有openssl,可以说我们的信息都是在裸奔

    图形化配置网络/服务/防火墙

    • setuptool        #安装setup命令工具

    • ntsysv            #安装setup工具配套的系统服务组件

    • system-config-securitylevel-tui     #安装setup工具配套的防火墙配置组件

    • NetworkManager-tui                    #安装setup工具配套的网络配置组件

    • authconfig-gtk                              #安装setup工具配套的验证配置组件

    • system-config-keyboard              #安装setup工具配套的键盘配置组件

    • bind-utils                                      #解决没有nslookup命令

    yum -y install setuptool
    yum -y install ntsysv
    yum -y install system-config-securitylevel-tui
    yum -y install NetworkManager-tui authconfig-gtk
    yum -y install system-config-keyboard
    yum -y install bind-utils

    一键安装

    yum -y install setuptool ntsysvsystem-config-securitylevel-tui networkManager-tui authconfig-gtk system-config-keyboard bind-utils

    5、关闭防火墙(测试环境)

    systemctl disable firewalld
    systemctl stop firewalld
    sed -i 's/^ *SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config

    6、添加普通用户并进行sudo授权管理

    7、默认打开vim增加行号

    vim 要默认打开的时候显示行号,这样就可以不用每次编辑的时候在手动在命令模式下:set number 来显示行号。

    具体做法是: 创建一个 .vimrc的配置文件。

    在启动vim时,当前用户根目录下的.vimrc文件会被自动读取,该文件可以包含一些设置甚至脚本,所以,一般情况下把.vimrc文件创建在当前用户的根目录下比较方便,即创建的命令为:

    $vi ~/.vimrc

    往文件里面添加内容: set number , 保存退出。

    8、更改ssh默认端口

    9、禁止root远程登录 切记给系统添加普通用户,给su到root的权限

    10、root用户密码输入错误三次,锁定账户一段时间

    11、设置时区并同步时间

    12、历史命令显示操作时间

    13、SSH超时时间

    14、禁止定时任务向发送邮件

    sed -i 's/^MAILTO=root/MAILTO=""/' /etc/crontab

     

    不断更新

     

     

     

    展开全文
  • 程序员的数学:优化理论

    千人学习 2020-03-11 14:43:07
    程序员的数学-优化理论
  • 如何优化MySQL千万级大表,我写了6000字的解读

    万次阅读 多人点赞 2019-10-22 13:39:49
    千万级大表如何优化,这是一个很有技术含量的问题,通常我们的直觉思维都会跳转到拆分或者数据分区,在此我想做一些补充和梳理,想和大家做一些这方面的经验总结,也欢迎大家提出建议。 从一开始脑海里开始也是...
        

    这是学习笔记的第 2138 篇文章

      640?wx_fmt=gif

    千万级大表如何优化,这是一个很有技术含量的问题,通常我们的直觉思维都会跳转到拆分或者数据分区,在此我想做一些补充和梳理,想和大家做一些这方面的经验总结,也欢迎大家提出建议。 

    从一开始脑海里开始也是火光四现,到不断的自我批评,后来也参考了一些团队的经验,我整理了下面的大纲内容。

    640?wx_fmt=png

    既然要吃透这个问题,我们势必要回到本源,我把这个问题分为三部分:

    “千万级”,“大表”,“优化”,

    也分别对应我们在图中标识的

    “数据量”,“对象”和“目标”。

    我来逐步展开说明一下,从而给出一系列的解决方案。 

    1.数据量:千万级

    千万级其实只是一个感官的数字,就是我们印象中的数据量大。 这里我们需要把这个概念细化,因为随着业务和时间的变化,数据量也会有变化,我们应该是带着一种动态思维来审视这个指标,从而对于不同的场景我们应该有不同的处理策略。

     

    1) 数据量为千万级,可能达到亿级或者更高

    通常是一些数据流水,日志记录的业务,里面的数据随着时间的增长会逐步增多,超过千万门槛是很容易的一件事情。

    2) 数据量为千万级,是一个相对稳定的数据量

    如果数据量相对稳定,通常是在一些偏向于状态的数据,比如有1000万用户,那么这些用户的信息在表中都有相应的一行数据记录,随着业务的增长,这个量级相对是比较稳定的。

    3) 数据量为千万级,不应该有这么多的数据

    这种情况是我们被动发现的居多,通常发现的时候已经晚了,比如你看到一个配置表,数据量上千万;或者说一些表里的数据已经存储了很久,99%的数据都属于过期数据或者垃圾数据。

    数据量是一个整体的认识,我们需要对数据做更近一层的理解,这就可以引出第二个部分的内容。 

    2.对象:数据表

    数据操作的过程就好比数据库中存在着多条管道,这些管道中都流淌着要处理的数据,这些数据的用处和归属是不一样的。

    一般根据业务类型把数据分为三种:

    (1)流水型数据

    流水型数据是无状态的,多笔业务之间没有关联,每次业务过来的时候都会产生新的单据,比如交易流水、支付流水,只要能插入新单据就能完成业务,特点是后面的数据不依赖前面的数据,所有的数据按时间流水进入数据库。

    (2)状态型数据

    状态型数据是有状态的,多笔业务之间依赖于有状态的数据,而且要保证该数据的准确性,比如充值时必须要拿到原来的余额,才能支付成功。

    (3)配置型数据

    此类型数据数据量较小,而且结构简单,一般为静态数据,变化频率很低。

    至此,我们可以对整体的背景有一个认识了,如果要做优化,其实要面对的是这样的3*3的矩阵,如果要考虑表的读写比例(读多写少,读少写多...),那么就会是3*3*4=24种,显然做穷举是不显示的,而且也完全没有必要,可以针对不同的数据存储特性和业务特点来指定不同的业务策略。 

    对此我们采取抓住重点的方式,把常见的一些优化思路梳理出来,尤其是里面的核心思想,也是我们整个优化设计的一把尺子,而难度决定了我们做这件事情的动力和风险。

    数据量增长情况

    数据表类型

    业务特点

    优化核心思想

    优化难度

    数据量为千万级,是一个相对稳定的数据量

    状态表

    OLTP业务方向

    能不拆就不拆读需求水平扩展

    ****

    数据量为千万级,可能达到亿级或者更高

    流水表

    OLTP业务的历史记录

    业务拆分,面向分布式存储设计

    ****

    OLAP业务统计数据源

    设计数据统计需求存储的分布式扩展

    ***

    数据量为千万级,不应该有这么多的数据

    配置表

    通用业务

    小而简,避免大一统

    *

    而对于优化方案,我想采用面向业务的维度来进行阐述。 

    3.目标:优化

    在这个阶段,我们要说优化的方案了,总结的有点多,相对来说是比较全了。

    整体分为五个部分:

    640?wx_fmt=png

    其实我们通常所说的分库分表等方案只是其中的一小部分,如果展开之后就比较丰富了。

    640?wx_fmt=png

    其实不难理解,我们要支撑的表数据量是千万级别,相对来说是比较大了,DBA要维护的表肯定不止一张,如何能够更好的管理,同时在业务发展中能够支撑扩展,同时保证性能,这是摆在我们面前的几座大山。

    我们分别来说一下这五类改进方案:

    优化设计方案1.规范设计

    在此我们先提到的是规范设计,而不是其他高大上的设计方案。

    黑格尔说:秩序是自由的第一条件。在分工协作的工作场景中尤其重要,否则团队之间互相牵制太多,问题多多。

    规范设计我想提到如下的几个规范,其实只是属于开发规范的一部分内容,可以作为参考。

    640?wx_fmt=png

    规范的本质不是解决问题,而是有效杜绝一些潜在问题,对于千万级大表要遵守的规范,我梳理了如下的一些细则,基本可以涵盖我们常见的一些设计和使用问题,比如表的字段设计不管三七二十一,都是varchar(500),其实是很不规范的一种实现方式,我们来展开说一下这几个规范。

    1)配置规范

    (1)MySQL数据库默认使用InnoDB存储引擎。

    (2)保证字符集设置统一,MySQL数据库相关系统、数据库、表的字符集使都用UTF8,应用程序连接、展示等可以设置字符集的地方也都统一设置为UTF8字符集。

    注:UTF8格式是存储不了表情类数据,需要使用UTF8MB4,可在MySQL字符集里面设置。在8.0中已经默认为UTF8MB4,可以根据公司的业务情况进行统一或者定制化设置。

    (3)MySQL数据库的事务隔离级别默认为RR(Repeatable-Read),建议初始化时统一设置为RC(Read-Committed),对于OLTP业务更适合。

    (4)数据库中的表要合理规划,控制单表数据量,对于MySQL数据库来说,建议单表记录数控制在2000W以内。

    (5)MySQL实例下,数据库、表数量尽可能少;数据库一般不超过50个,每个数据库下,数据表数量一般不超过500个(包括分区表)。

    2)建表规范

    (1)InnoDB禁止使用外键约束,可以通过程序层面保证。

    (2)存储精确浮点数必须使用DECIMAL替代FLOAT和DOUBLE。

    (3)整型定义中无需定义显示宽度,比如:使用INT,而不是INT(4)。

    (4)不建议使用ENUM类型,可使用TINYINT来代替。

    (5)尽可能不使用TEXT、BLOB类型,如果必须使用,建议将过大字段或是不常用的描述型较大字段拆分到其他表中;另外,禁止用数据库存储图片或文件。

    (6)存储年时使用YEAR(4),不使用YEAR(2)。

    (7)建议字段定义为NOT NULL。

    (8)建议DBA提供SQL审核工具,建表规范性需要通过审核工具审核后

    3)命名规范

    (1)库、表、字段全部采用小写。

    (2)库名、表名、字段名、索引名称均使用小写字母,并以“_”分割。

    (3)库名、表名、字段名建议不超过12个字符。(库名、表名、字段名支持最多64个字符,但为了统一规范、易于辨识以及减少传输量,统一不超过12字符)

    (4)库名、表名、字段名见名知意,不需要添加注释。

    对于对象命名规范的一个简要总结如下表4-1所示,供参考。

    命名列表

    对象中文名称

    对象英文全称

    MySQL对象简写

    视图

    view

    view_

    函数

    function

    func_

    存储过程

    procedure

    proc_

    触发器

    trigger

    trig_

    普通索引

    index

    idx_

    唯一索引

    unique index

    uniq_

    主键索引

    primary key

    pk_

    4)索引规范

    (1)索引建议命名规则:idx_col1_col2[_colN]、uniq_col1_col2[_colN](如果字段过长建议采用缩写)。

    (2)索引中的字段数建议不超过5个。

    (3)单张表的索引个数控制在5个以内。

    (4)InnoDB表一般都建议有主键列,尤其在高可用集群方案中是作为必须项的。

    (5)建立复合索引时,优先将选择性高的字段放在前面。

    (6)UPDATE、DELETE语句需要根据WHERE条件添加索引。

    (7)不建议使用%前缀模糊查询,例如LIKE “%weibo”,无法用到索引,会导致全表扫描。

    (8)合理利用覆盖索引,例如:

    (9)SELECT email,uid FROM user_email WHERE uid=xx,如果uid不是主键,可以创建覆盖索引idx_uid_email(uid,email)来提高查询效率。

    (10)避免在索引字段上使用函数,否则会导致查询时索引失效。

    (11)确认索引是否需要变更时要联系DBA。

    5)应用规范

    (1)避免使用存储过程、触发器、自定义函数等,容易将业务逻辑和DB耦合在一起,后期做分布式方案时会成为瓶颈。

    (2)考虑使用UNION ALL,减少使用UNION,因为UNION ALL不去重,而少了排序操作,速度相对比UNION要快,如果没有去重的需求,优先使用UNION ALL。

    (3)考虑使用limit N,少用limit M,N,特别是大表或M比较大的时候。

    (4)减少或避免排序,如:group by语句中如果不需要排序,可以增加order by null。

    (5)统计表中记录数时使用COUNT(*),而不是COUNT(primary_key)和COUNT(1);InnoDB表避免使用COUNT(*)操作,计数统计实时要求较强可以使用Memcache或者Redis,非实时统计可以使用单独统计表,定时更新。

    (6)做字段变更操作(modify column/change column)的时候必须加上原有的注释属性,否则修改后,注释会丢失。

    (7)使用prepared statement可以提高性能并且避免SQL注入。

    (8)SQL语句中IN包含的值不应过多。

    (9)UPDATE、DELETE语句一定要有明确的WHERE条件。

    (10)WHERE条件中的字段值需要符合该字段的数据类型,避免MySQL进行隐式类型转化。

    (11)SELECT、INSERT语句必须显式的指明字段名称,禁止使用SELECT * 或是INSERT INTO table_name values()。

    (12)INSERT语句使用batch提交(INSERT INTO table_name VALUES(),(),()……),values的个数不应过多。

    优化设计方案2:业务层优化

    业务层优化应该是收益最高的优化方式了,而且对于业务层完全可见,主要有业务拆分,数据拆分和两类常见的优化场景(读多写少,读少写多)

    640?wx_fmt=png

    1)业务拆分

    ü 将混合业务拆分为独立业务

    ü 将状态和历史数据分离

    业务拆分其实是把一个混合的业务剥离成为更加清晰的独立业务,这样业务1,业务2。。。独立的业务使得业务总量依旧很大,但是每个部分都是相对独立的,可靠性依然有保证。

    对于状态和历史数据分离,我可以举一个例子来说明。

    例如:我们有一张表Account,假设用户余额为100。

    640?wx_fmt=png

    我们需要在发生数据变更后,能够追溯数据变更的历史信息,如果对账户更新状态数据,增加100的余额,这样余额为200。

    这个过程可能对应一条update语句,一条insert语句。

    对此我们可以改造为两个不同的数据源,account和account_hist

    在account_hist中就会是两条insert记录,如下:

    640?wx_fmt=png

    而在account中则是一条update语句,如下:

    640?wx_fmt=png

    这也是一种很基础的冷热分离,可以大大减少维护的复杂度,提高业务响应效率。

    2)数据拆分

    2.1 按照日期拆分,这种使用方式比较普遍,尤其是按照日期维度的拆分,其实在程序层面的改动很小,但是扩展性方面的收益很大。

    • 数据按照日期维度拆分,如test_20191021

    • 数据按照周月为维度拆分,test_201910

    • 数据按照季度,年维度拆分,test_2019

    2.2 采用分区模式,分区模式也是常见的使用方式,采用hash,range等方式会多一些,在MySQL中我是不大建议使用分区表的使用方式,因为随着存储容量的增长,数据虽然做了垂直拆分,但是归根结底,数据其实难以实现水平扩展,在MySQL中是有更好的扩展方式。

    2.3 读多写少优化场景

    采用缓存,采用Redis技术,将读请求打在缓存层面,这样可以大大降低MySQL层面的热点数据查询压力。

    2.4 读少写多优化场景,可以采用三步走:

    1) 采用异步提交模式,异步对于应用层来说最直观的就是性能的提升,产生最少的同步等待。

    2) 使用队列技术,大量的写请求可以通过队列的方式来进行扩展,实现批量的数据写入。

    3) 降低写入频率,这个比较难理解,我举个例子

    对于业务数据,比如积分类,相比于金额来说业务优先级略低的场景,如果数据的更新过于频繁,可以适度调整数据更新的范围(比如从原来的每分钟调整为10分钟)来减少更新的频率。

    例如:更新状态数据,积分为200,如下图所示

    640?wx_fmt=png

    可以改造为,如下图所示。

    640?wx_fmt=png

    如果业务数据在短时间内更新过于频繁,比如1分钟更新100次,积分从100到10000,则可以根据时间频率批量提交。

    例如:更新状态数据,积分为100,如下图所示。

    640?wx_fmt=png

    无需生成100个事务(200SQL语句)可以改造为2SQL语句,如下图所示。

    640?wx_fmt=png

    对于业务指标,比如更新频率细节信息,可以根据具体业务场景来讨论决定。

    优化设计方案3:架构层优化

    架构层优化其实就是我们认为的那种技术含量很高的工作,我们需要根据业务场景在架构层面引入一些新的花样来。

    640?wx_fmt=png

    3.1.系统水平扩展场景

    3.1.1采用中间件技术,可以实现数据路由,水平扩展,常见的中间件有MyCATShardingSphere,ProxySQL等

    640?wx_fmt=jpeg

    3.1.2 采用读写分离技术,这是针对读需求的扩展,更侧重于状态表,在允许一定延迟的情况下,可以采用多副本的模式实现读需求的水平扩展,也可以采用中间件来实现,如MyCAT,ProxySQL,MaxScale,MySQL Router

    640?wx_fmt=png

    3.1.3 采用负载均衡技术,常见的有LVS技术或者基于域名服务的Consul技术

    3.2.兼顾OLTP+OLAP的业务场景,可以采用NewSQL,优先兼容MySQL协议的HTAP技术栈,如TiDB

    3.3.离线统计的业务场景,有几类方案可供选择。

    3.3.1 采用NoSQL体系,主要有两类,一类是适合兼容MySQL协议的数据仓库体系,常见的有Infobright或者ColumnStore,另外一类是基于列式存储,属于异构方向,如HBase技术

    3.3.2 采用数仓体系,基于MPP架构,如使用Greenplum统计,如T+1统计

    优化设计方案4:数据库优化

    数据库优化,其实可打的牌也不少,但是相对来说空间没有那么大了,我们来逐个说一下。

    640?wx_fmt=png

    4.1 事务优化

    根据业务场景选择事务模型,是否是强事务依赖

    对于事务降维策略,我们来举出几个小例子来。

    4.1.1 降维策略1:存储过程调用转换为透明的SQL调用

    对于新业务而言,使用存储过程显然不是一个好主意,MySQL的存储过程和其他商业数据库相比,功能和性能都有待验证,而且在目前轻量化的业务处理中,存储过程的处理方式太“重”了。

    有些应用架构看起来是按照分布式部署的,但在数据库层的调用方式是基于存储过程,因为存储过程封装了大量的逻辑,难以调试,而且移植性不高,这样业务逻辑和性能压力都在数据库层面了,使得数据库层很容易成为瓶颈,而且难以实现真正的分布式。

    所以有一个明确的改进方向就是对于存储过程的改造,把它改造为SQL调用的方式,可以极大地提高业务的处理效率,在数据库的接口调用上足够简单而且清晰可控。

    4.1.2 降维策略2DDL操作转换为DML操作

    有些业务经常会有一种紧急需求,总是需要给一个表添加字段,搞得DBA和业务同学都挺累,可以想象一个表有上百个字段,而且基本都是name1,name2……name100,这种设计本身就是有问题的,更不用考虑性能了。究其原因,是因为业务的需求动态变化,比如一个游戏装备有20个属性,可能过了一个月之后就增加到了40个属性,这样一来,所有的装备都有40个属性,不管用没用到,而且这种方式也存在诸多的冗余。

    我们在设计规范里面也提到了一些设计的基本要素,在这些基础上需要补充的是,保持有限的字段,如果要实现这些功能的扩展,其实完全可以通过配置化的方式来实现,比如把一些动态添加的字段转换为一些配置信息。配置信息可以通过DML的方式进行修改和补充,对于数据入口也可以更加动态、易扩展。

    4.1.3 降维策略3:Delete操作转换为高效操作

    有些业务需要定期来清理一些周期性数据,比如表里的数据只保留一个月,那么超出时间范围的数据就要清理掉了,而如果表的量级比较大的情况下,这种Delete操作的代价实在太高,我们可以有两类解决方案来把Delete操作转换为更为高效的方式。 

    第一种是根据业务建立周期表,比如按照月表、周表、日表等维度来设计,这样数据的清理就是一个相对可控而且高效的方式了。 

    第二种方案是使用MySQL rename的操作方式,比如一张2千万的大表要清理99%的数据,那么需要保留的1%的数据我们可以很快根据条件过滤补录,实现“移形换位”。

    4.2 SQL优化

    其实相对来说需要的极简的设计,很多点都在规范设计里面了,如果遵守规范,八九不离十的问题都会杜绝掉,在此补充几点:

    4.2.1 SQL语句简化,简化是SQL优化的一大利器,因为简单,所以优越。

    4.2.2 尽可能避免或者杜绝多表复杂关联,大表关联是大表处理的噩梦,一旦打开了这个口子,越来越多的需求需要关联,性能优化就没有回头路了,更何况大表关联是MySQL的弱项,尽管Hash Join才推出,不要像掌握了绝对大杀器一样,在商业数据库中早就存在,问题照样层出不穷。

    4.2.3 SQL中尽可能避免反连接,避免半连接,这是优化器做得薄弱的一方面,什么是反连接,半连接?其实比较好理解,举个例子,not in ,not exists就是反连接,in,exists就是半连接,在千万级大表中出现这种问题,性能是几个数量级的差异。 

    4.3 索引优化

    应该是大表优化中需要把握的一个度。

    4.3.1 首先必须有主键,规范设计中第一条就是,此处不接收反驳。

    4.3.2 其次,SQL查询基于索引或者唯一性索引,使得查询模型尽可能简单。

    4.3.3 最后,尽可能杜绝范围数据的查询,范围扫描在千万级大表情况下还是尽可能减少。

    优化设计方案4:管理优化

    这部分应该是在所有的解决方案中最容易被忽视的部分了,我放在最后,在此也向运维同事致敬,总是为很多认为本应该正常的问题尽职尽责(背锅)。

    640?wx_fmt=png

    千万级大表的数据清理一般来说是比较耗时的,在此建议在设计中需要完善冷热数据分离的策略,可能听起来比较拗口,我来举一个例子,把大表的Drop 操作转换为可逆的DDL操作。

    Drop操作是默认提交的,而且是不可逆的,在数据库操作中都是跑路的代名词,MySQL层面目前没有相应的Drop操作恢复功能,除非通过备份来恢复,但是我们可以考虑将Drop操作转换为一种可逆的DDL操作。

    MySQL中默认每个表有一个对应的ibd文件,其实可以把Drop操作转换为一个rename操作,即把文件从testdb迁移到testdb_arch下面;从权限上来说,testdb_arch是业务不可见的,rename操作可以平滑的实现这个删除功能,如果在一定时间后确认可以清理,则数据清理对于已有的业务流程是不可见的,如下图所示。

    640?wx_fmt=png

    此外,还有两个额外建议,一个是对于大表变更,尽可能考虑低峰时段的在线变更,比如使用pt-osc工具或者是维护时段的变更,就不再赘述了。

    最后总结一下,其实就是一句话:

    千万级大表的优化是根据业务场景,以成本为代价进行优化的,绝对不是孤立的一个层面的优化

    近期热文:

    个人新书 《MySQL DBA工作笔记》

    个人公众号:jianrong-notes

    QQ群号:763628645

    QQ群二维码如下,个人微信号:jeanron100, 添加请注明:姓名+地区+职位,否则不予通过

    640?wx_fmt=png640?wx_fmt=png

    在看,让更多人看到

    展开全文
  • 优化理论与方法

    千次阅读 2019-04-23 12:28:47
    优化问题 :eg:,其中x在控制问题中被称为为控制决策变量;在数学优化中叫做决策量。无论是最优控制还是数学优化(数学规划)都是优化问题,即都是这样的形式。 1. 优化的两个基本问题 确定一个优化的必要或/和...

    优化问题 :eg:{min}_xf\left ( x \right ) st. x\in D,其中x在控制问题中被称为为控制决策变量;在数学优化中叫做决策量。无论是最优控制还是数学优化(数学规划)都是优化问题,即都是{min}_xf\left ( x \right ) st. x\in D这样的形式。

    1. 优化的两个基本问题

    • 确定一个优化的必要或/和充分的条件(建模)。
    • 设计一个数值程序(算法的设计+程序的实现)。

    遗传算法在弱优化或无约束优化问题中应用较好。

    2. 优化的相关概念

    静态    vs    动态    数学优化\leftrightarrow最优控制;

    连续    vs   离散    数学优化的离散与连续问题\leftrightarrow控制问题的连续与离散问题;

    凸   vs   非凸   既可能与目标有关,又可能与约束有关;

    完美   vs   满意   结果的完美解与满意解;

    严格   vs   启发   方法在数学上是否严格收敛到最优与否。

    2.1 静态优化(参数优化、数学规划等方法)

    • 对变量进行优化;
    • 约束条件与目标为代数方程或不等式。

    2.2 动态优化(变分问题、最优控制)

    • 对函数进行优化(例如最优决策路径)(函数未知)
    • 目标为积分型泛函;
    • 约束条件包含微分方程。

    2.3 连续优化与离散优化

    • 可行域(决策空间)
    •     0-1规划
    •     整数规划
    • 时间序列
    •     离散时间的动态规划——差分描述
    •     连续时间的动态规划——微分描述

    2.4 确定性优化与随机优化

    • DP 动态优化 确定性;
    • MDP Markov决策过程 随机性

    2.5 凸与非凸

    • 凸集;
    • 凸函数

    2.6 启发与随机化搜索

    • 启发式+随机化=高级启发或超级启发(遗传算法、模拟退火算法、蚁群算法);

    2.7 完美解与满意解

    • 一般需要对满意解进行评价

    3 优化方法

    迭代    vs   解析    计算机喜爱迭代方法,并且这种方法效率高;

    串行    vs    并行    

    求导    vs    搜索

    点对点    vs    集到集

    解析    vs    启发

    注:结构知识绝对重要,搜索方法应当在结构信息的指导下进行搜索。启发、学习、人的才智以及软优化在求解方法中占有重要地位。

    一些常用的迭代方法

    • 梯度法(利用了梯度结构信息)
    • 牛顿法(利用了梯度+Hessen矩阵等结构信息)
    • BFGS (共轭梯度结构信息)
    展开全文
  • 常见的web性能优化方法

    万次阅读 多人点赞 2017-06-07 15:47:49
    前端优化是复杂的,针对方方面面的资源都有不同的方式。那么,前端优化的目的是什么 ?  1. 从用户角度而言,优化能够让页面加载得更快、对用户的操作响应得更及时,能够给用户提供更为友好的体验。  2. 从服务商...
  • -O1,-O2,-O3编译优化知多少

    万次阅读 多人点赞 2016-07-07 00:32:59
    1.从.c文件到可执行文件,其间经历了几步? 高级语言是偏向人,按照人的思维方式设计的,机器对这些可是莫名奇妙,不知所谓。那从高级语言是如何过渡到机器语言的呢?这可是一个漫长的旅途呀!...
  • sql优化的几种方式

    万次阅读 多人点赞 2019-11-11 09:15:50
    一、为什么要对SQL进行优化 我们开发项目上线初期,由于业务数据量相对较少,一些SQL的执行效率对程序运行效率的影响不太明显,而开发和运维人员也无法判断SQL对程序的运行效率有多大,故很少针对SQL进行专门的优化...
  • 三种快排,四种优化

    千次阅读 2018-08-31 16:18:07
    1、快速排序的基本思想: 快速排序使用分治的思想,通过一趟排序将待排序列分割成两部分,其中一部分记录的关键字均比另一部分记录的关键字小。之后分别对这两部分记录继续进行排序,以达到整个序列有序的目的。...
  • 优化方法总结:SGD,Momentum,AdaGrad,RMSProp,Adam

    万次阅读 多人点赞 2018-11-21 13:32:30
    1. SGDBatch Gradient Descent在每一轮的训练过程中,Batch Gradient Descent算法用整个训练集的数据计算cost fuction的梯度,并用该梯度对模型参数进行更新:Θ=Θ−α⋅▽ΘJ(Θ)\Theta = \Theta -\alpha \cdot \...
  • 优化理论与凸优化到底是干嘛的?

    万次阅读 多人点赞 2017-12-17 10:46:35
    优化的定义 1.1 凸优化 ...1.1 凸优化优化问题目前在机器学习,数据挖掘等领域应用非常广泛,因为机器学习简单来说,主要做的就是优化问题,先初始化一下权重参数,然后利用优化方法来优化这个
  • SEO优化网站教程6

    万次阅读 2019-08-23 09:04:49
    SEO优化网站教程之6个经典软件操作顺序6个经典软件操作顺序网站关键词优化到百度首页其主要关键在于网站内容关联建设,掌握【网站标题-网站首页长尾关键词建设-文章标题-文章内容】这三者紧密和高度关联性。...
  • 数据库优化 - SQL优化

    万次阅读 多人点赞 2019-12-13 10:33:07
    以实际SQL入手,带你一步一步走上SQL优化之路!
  • SEO优化网站教程4

    万次阅读 2019-08-23 09:06:35
    SEO优化网站教程之文章插入长尾词内链技巧文章插入长尾词内链技巧下面我们举例说明一:下面我们举例说明二:有需要更全面的SEO优化网站软件工具及软件操作文档可以联系博主,会有更详细的教程,系统的帮助您的网站...
  • Win10必做的性能优化

    万次阅读 多人点赞 2019-05-17 10:14:16
    Windows10系统目前慢慢成为主流的操作系统,win7目前已经不再提供技术支持,到2020年正式退役。...由于win10系统功能变多,系统也变得臃肿,下面就给大家讲讲Windows10必做的优化。 1.关闭家...
  • 粒子群优化算法(PSO)

    万次阅读 多人点赞 2019-07-22 09:51:31
    粒子群优化算法(Partical Swarm Optimization PSO),粒子群中的每一个粒子都代表一个问题的可能解,通过粒子个体的简单行为,群体内的信息交互实现问题求解的智能性。由于PSO操作简单、收敛速度快,...
  • 数学优化入门:凸优化

    万次阅读 多人点赞 2018-05-12 11:39:20
    做科研时,曾花了段时间学习凸优化,后来发现ML中其应用也非常普遍,想来今后可能还会接触,干脆做个系统的总结,方便以后查询。 博文内容主要参考Boyd(Stanford)的Convex Optimization,配套的slides,以及部分...
  • 多目标优化问题的算法及其求解

    万次阅读 多人点赞 2018-11-19 15:13:13
    多目标优化问题的算法及其求解 一、多目标优化问题   多目标优化是在现实各个领域中都普遍存在的问题,每个目标不可能都同时达到最优,必须各有权重。但是,究竟要怎样分配这样的权重,这已经成为人们...
  • 本文全面讲解性能优化中的所有知识,献上一份 Android性能优化的详细攻略, 含:优化方向、原因 &amp; 具体优化方案,希望你们会喜欢 文章较长,建议预留较长时间阅读 / 收藏 目录 1. 性能优化...
  • sql优化(面试必问一)

    万次阅读 多人点赞 2018-03-28 12:37:51
    前言:7月13号 至7月26号面试总结比较棘手的的问题:近来面试找工作经常会遇见这种问题: 做过数据库优化吗?大数据量基础过吗?系统反应慢怎么查询?这时候就需要你谈一下sql优化相关的内容 , 一下几个方面1、慢...
1 2 3 4 5 ... 20
收藏数 2,383,065
精华内容 953,226
关键字:

优化