Postgresql Yii2和TimescaleDB:GridView在大表上速度非常慢

Postgresql Yii2和TimescaleDB:GridView在大表上速度非常慢,postgresql,performance,gridview,yii2,timescaledb,Postgresql,Performance,Gridview,Yii2,Timescaledb,将Yi2与TimescaleDB(用于时间序列数据的PostgreSQL扩展)一起使用在大型表(大于10亿行)上速度非常慢 我认为这来自于函数getTotalCount(),在该函数中,调用getTotalCount()对每个页面进行分页 我们从中了解到。如果我们用“coorrect”解决方案替换模型中的函数getTotalCount(),如下所示 static public function getTotalCount() { $connection = Yii::$app->g

将Yi2与TimescaleDB(用于时间序列数据的PostgreSQL扩展)一起使用在大型表(大于10亿行)上速度非常慢

我认为这来自于函数
getTotalCount()
,在该函数中,调用getTotalCount()对每个页面进行分页

我们从中了解到。如果我们用“coorrect”解决方案替换模型中的函数
getTotalCount()
,如下所示

static public function getTotalCount()
{
    $connection = Yii::$app->getDb();
    $command = $connection->createCommand("
        SELECT h.schema_name,
            h.table_name,
            h.id AS table_id,
            h.associated_table_prefix,
            row_estimate.row_estimate
        FROM _timescaledb_catalog.hypertable h
        CROSS JOIN LATERAL ( SELECT sum(cl.reltuples) AS row_estimate
        FROM _timescaledb_catalog.chunk c
        JOIN pg_class cl ON cl.relname = c.table_name
        WHERE c.hypertable_id = h.id and h.table_name = 'value'
        GROUP BY h.schema_name, h.table_name) row_estimate
        ORDER BY \"schema_name\", \"table_name\";
    ");

    $result = $command->queryAll();
    return floatval($result[0]["row_estimate"]);
}
但是,我们真的必须为分页执行此查询吗

这似乎相当复杂。如何对此进行优化?也许只是返回一个非常大但固定的数字,因为没有人需要超过十亿页的分页

例如:

const LARGE_NUM = 1000;
static public function getTotalCount() 
{
    if (Yii::$app->session->get("mytable-rows")>MyClass::LARGE_NUM) {
        return MyClass::LARGE_NUM; 
    } 
    $totalRows = parent::getTotalCount();
    Yii::$app->session->set("mytable-rows",$totalRows);
    return $totalRows;
}

这是一个有效且快速的解决方案吗?是否有危险的副作用?

前几页需要分页还是根本不使用分页?如果不需要分页,则将
BaseDataProvider
$pagination
属性设置为
false
应该可以防止
getTotalCount()
从GridView调用方法。我需要分页,但仅限于前50页左右。也许您可以在不使用计数/偏移量的情况下获取页面:例如,使用
WHERE date\u time>$start LIMIT$pagesize
。对于第一个,call
start
是未定义的(因此您只有limit子句),当用户单击next page按钮时,
start
是当前页面中显示的最新日期。但我不知道您的网格组件/框架是否支持此功能。@我们可以看到,覆盖
getTotalCount
将总计数存储在缓存中怎么样。这比使用会话要好,因为会话的寿命很短,并且不会在用户之间共享。您还可以由cron执行一些操作,以更新后台存储的总计数。@TmTron这没有帮助。为此,您需要实现自己的分页组件,并且仍然需要获取总行数以计算总页数或显示摘要中的记录总数。是否需要对前几页使用分页,或者根本不使用分页?如果不需要分页,则将
BaseDataProvider
$pagination
属性设置为
false
应该可以防止
getTotalCount()
从GridView调用方法。我需要分页,但仅限于前50页左右。也许您可以在不使用计数/偏移量的情况下获取页面:例如,使用
WHERE date\u time>$start LIMIT$pagesize
。对于第一个,call
start
是未定义的(因此您只有limit子句),当用户单击next page按钮时,
start
是当前页面中显示的最新日期。但我不知道您的网格组件/框架是否支持此功能。@我们可以看到,覆盖
getTotalCount
将总计数存储在缓存中怎么样。这比使用会话要好,因为会话的寿命很短,并且不会在用户之间共享。您还可以由cron执行一些操作,以更新后台存储的总计数。@TmTron这没有帮助。为此,您需要实现自己的分页组件,并且仍然需要获取总行数以计算总页数或在摘要中显示总记录数。