使用虚拟列减少索引的扫描行数

假设现在有一张表记录了每个人的基本信息

create TABLE `t_people` (
  `id` INT(11) DEFAULT NULL ,
  `name` VARCHAR(20) DEFAULT NULL ,
  `age` INT(11) DEFAULT NULL ,
  `info` VARCHAR(255) DEFAULT NULL
)ENGINE = InnoDB;

里面总共有三条数据

INSERT INTO test.t_people (id, name, age, info, name_fist) VALUES (1, '张三', 8, null, '张');
INSERT INTO test.t_people (id, name, age, info, name_fist) VALUES (2, '李四', 12, null, '李');
INSERT INTO test.t_people (id, name, age, info, name_fist) VALUES (3, '张三', 11, null, '张');

现在我们需要找出姓名开头是张且年龄等于8的数据。

一、我们很容易想到给表添加名字和年龄的联合索引。

ALTER TABLE t_people ADD INDEX name_age_index(name, age);

搜索语句:

EXPLAIN SELECT * FROM t_people WHERE name LIKE '张%' AND age=8;

执行结果如下,总共扫描了2行

二、使用虚拟列

ALTER TABLE t_people add name_fist VARCHAR(2) GENERATED ALWAYS
as (left(name,1)),ADD INDEX name_fist_age_index(name_fist, age);

语句如下:

EXPLAIN SELECT * FROM t_people WHERE name_fist='张' AND age=8;

执行结果如下,只扫描了1行

总结:

1.虚拟列在插入的时候不能指定值,更新的时候也不能主动修改,它的值会根据定义自动修改。

2.查询优化的过程往往就是较少扫描行数的过程。

Visits: 1812

leetcode-最大子序和

题目:

给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。

示例:

输入: [-2,1,-3,4,-1,2,1,-5,4],
输出: 6
解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/maximum-subarray

动态规划解法的思路:

  • 假定第一个元素为最终返回的子序和,设为result
  • 设定数组元素相加和为 sum
  • 遍历数组,将元素相加获得的sum与result对比,取最大
  • 时间复杂度 O(n)

代码:

class MaxSubArray
{
    function solution($nums)
    {
        $result = $nums[0];
        $sum = 0;

        for ($i=1; $i < count($nums); $i++) {
            if ($sum > 0) {
                $sum += $nums[$i];
            } else {
                $sum = $nums[$i];
            }

            $result = max($result, $sum);
        }

        return $result;
    }
}

Visits: 356

leetcode-斐波那契数

class Fib
{
    //自底向上计算结果
    public function solution($N)
    {
        $current = 0;
        $next = 1;
        while ($N-- > 0) {
            $next = $next + $current;
            $current = $next - $current;
        }
        return (int)$current;
    }
}

$fib = new Fib();
$res = $fib->solution(10);

算法使用了自底向上的方法,通过迭代计算斐波那契数子问题的结果,最后获得最终结果。

复杂度分析:

  • 时间复杂度:O(N)O(N)。
  • 空间复杂度:O(N)O(N),使用了空间大小为N 的数组。

github练习仓库

题目来源:力扣中国-斐波那契数

Visits: 391

PHP中时间函数strtotime记录容易出现bug的情况

11月的时候,同事做了一个功能,大致为获取上个月的表单并提醒未提交表单的人提交,该功能在12月发布。但是在12.31号,本该提醒的是11月未提交表单的人,却提醒了12月未提交表单的人。查看代码的时候发现用的函数没有错误,于是上网搜索问题,结果原来是strtotime函数逻辑问题。

代码如下:

$subMonth=Carbon::now()->subMonth()->toDateTimeString();<br>
$year=date('Y',strtotime($subMonth));<br>
$month=date('m',strtotime($subMonth));

之后有同事提醒之前曾经看过鸟哥的博客有解释过这个问题。

date内部的对于这种事情的处理逻辑:

  • 1. 先做-1 month, 那么当前是07-31, 减去一以后就是06-31.
  • 2. 再做日期规范化, 因为6月没有31号, 所以就好像2点60等于3点一样, 6月31就等于了7月1

更改代码为一下生效

$year = date("Y", strtotime('last day of last month', time()));
$month = date("m", strtotime('last day of last month', time()));

参考: http://www.laruence.com/2018/07/31/3207.html

Visits: 108