举杯邀月

Yii2 使用验证器实现查询分表数据

摘要:对于数据量很大但历史数据不需要很实时获取的数据,我们往往才用分表进行数据的存在,比如利用表名加日期确定数据的储存位置,但是对于yii查询而言,默认模型是只针对一个表的,所以我们需要找方法去完成

对于数据量很大但历史数据不需要很实时获取的数据,我们往往才用分表进行数据的存在,比如利用表名加日期确定数据的储存位置,

比如统计的数据,一般我们看的都是最近一周甚至一个月的热数据,去年前年的数据可能只是在总整体汇总的时候才会用。但是统计数据数据量大,尤其是各种维度复杂的时候,会造成查询慢甚至超时的情况。

分表储存是解决这个困扰的一个办法,比如最近七天的按天表存储,最近一月的按月表存储,然后是年表等。这样做的目的是减少对数据的查询,结构大致如下:

info_20190801
info_20190802
info_20190803
info_20190804
info_20190805
info_20190806
info_20190807
……
info_week       # 最近一周的数据
info_month      # 最近一月的数据
info_201908
info_201907
……
info_2019
info_2018
……
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

这样拆分,我们就根据需要查询的日期去查询不同的表,比如:

假设今天是 2019年8月7号
查询今天的数据,我们只需要查 info_20190807 表
查询八月4号到7号的数据,我们只需要查 info_week 表

另外至于天表保留几天这个就需要根据情况而定了。

但是对于yii查询而言,默认模型是只针对一个表的,所以我们需要找方法去完成。

首先,模型的内容:


namespace common\models\mysql;

use Yii;
use yii\db\ActiveQuery;

class Info extends \yii\db\ActiveRecord
{

    public static $tableName = '';  //定义需要的表名

    /**
     * @inheritdoc
     */
    public static function tableName()
    {
        return 'info'.self::$tableName;
    }

    /** 这里是其他代码 **/
       
    /** 重写find查询方法
     * @param string $tableName
     * @return object|ActiveQuery
     * @throws \yii\base\InvalidConfigException
     */
    public static function find($tableName='')
    {
        self::$tableName = $tableName;
        return Yii::createObject(ActiveQuery::className(), [get_called_class(), ['from' => [static::tableName()]]]);
    }

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

然后定义搜索模型:


namespace common\models\form;

use common\models\mysql\Info;

class InfoSearch extends Info{

    public $params;          //传递的参数
    public $table_name = '';
    public $start_time;      //开始时间
    public $end_time;        //结束时间

    /**
     * @description:  rules
     * @updater:
     */
    public function rules()
    {
        return [
            [['start_time', 'end_time'], 'integer'],                                  //时间必须是字符串
            [['start_time', 'end_time'], 'default', 'value'=> date('Ymd')],   //默认为当天
            [['start_time'], 'common\validators\DateValidator'],                      //定义验证器
        ];
    }

    public function search()
    {
        $this->load($this->params, '');
        if (!$this->validate()){
            // 数据验证异常   array_values($this->getFirstErrors())[0]
        }

        $result = self::find($this->table_name)
            ->andFilterWhere(['between', 'ymd', $this->start_time, $this->end_time])
            ->createCommand()->getRawSql();

        var_dump($result);
    }

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40

最后,写我们验证用的


namespace common\validators;

use yii\validators\Validator;

class DateValidator extends Validator
{

    public $startAttribute = 'start_time';
    public $endAttribute = 'end_time';
    public $tableName = 'table_name';

    public function validateAttribute($model, $attribute)
    {
        $startName = $this->startAttribute;
        $endName = $this->endAttribute;
        $tableName = $this->tableName;

        $newTime = date('Ymd');   //当前年月日
        if ($model->$startName < 20180601 || $model->$endName > $newTime)
            $this->addError($model, $attribute, '查询时间不在范围');
        if ($model->$startName > $model->$endName)
            $this->addError($model, $attribute, '开始日期不能大于结束日期');

        /** 获取查询表名 **/
        if($model->$tableName === ''){
            if($model->$startName == $model->$endName && $model->$startName >= date('Ymd', strtotime('-6 days'))){//今天7天每天 查询天表
//            if($model->$startName == $model->$endName){//今天7天每天 查询天表
                $model->$tableName = $model->$startName;
            }elseif($model->$startName >= date('Ymd', strtotime('-6 days'))){       //最近7天查询周表(不包含今天)
                $model->$tableName = '_week';
            }elseif($model->$startName >= date('Ymd', strtotime('-29 days'))){      //最近30天查询月表
                $model->$tableName = '_month';
            }else{
                $model->$tableName = date('Y', strtotime($model->$startName));             //查询年表
            }
        }
    }

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40

这样,我们在调用模型搜索的时候就可以根据日期查询不同的表了,当然不同的情况需要去做不同的程序修改,但整体思路就是如此了。

作者:举杯邀月

出处: http://www.hug-code.cn/archives/5fc707387fe5e.html

2020-06-08 标签: yii2php