【发布时间】:2015-04-16 07:32:07
【问题描述】:
我在Yii2 中使用SqlDataProvider,这是一般示例:
$count = Yii::$app->db->createCommand('
SELECT COUNT(*) FROM user WHERE status=:status
', [':status' => 1])->queryScalar();
$dataProvider = new SqlDataProvider([
'sql' => 'SELECT * FROM user WHERE status=:status',
'params' => [':status' => 1],
'totalCount' => $count,
'sort' => [
'attributes' => [
'age',
'name' => [
'asc' => ['first_name' => SORT_ASC, 'last_name' => SORT_ASC],
'desc' => ['first_name' => SORT_DESC, 'last_name' => SORT_DESC],
'default' => SORT_DESC,
'label' => 'Name',
],
],
],
'pagination' => [
'pageSize' => 20,
],
]);
您可以看到,这在获取实际数据结果的SqlDataProvider 中的实际查询之前在查询中执行了COUNT。
但是我更喜欢使用SLC_CALC_FOUND_ROWS,因为此数字是一种更可靠的方法,可以获取与 DataProvider 中查询返回的实际行数相匹配的正确数字,因为匹配的行可能会被添加或删除在COUNT 查询和SqlDataProvider 查询之间,因此我需要更可靠的东西。
我可以锁定表格,但我认为这不是明智之举,因此我需要使用 SQL_CALC_FOUND_ROWS 来获得正确的数量,但我不确定如何使用 dataProvider 来做到这一点。
这将是执行我想要的代码:
$sql = $this->db->createCommand("SELECT FOUND_ROWS()");
$count = $sql->queryScalar();
$dataProvider->totalCount = $count;
...但这不起作用,所以正如我所说,我不确定如何实现代码以使用SqlDataProvider。
【问题讨论】:
-
SLC_CALC_FOUND_ROWS 会减慢您的脚本速度。 count(*) 使用索引并且工作得更快,因此您实际上不需要考虑“实际计数”,因为在这两个查询之间插入某些查询的可能性非常小。
-
@AlexanderRavikovich 这不一定是真的,这取决于您的应用程序。一些测试表明它较慢,有些则表明它更快 - 但是,如果您运行的网站流量比我认为的要高,那么最好追求准确性而不是速度,不是吗!?
-
我同意@AlexanderRavikovich。您可以毫无问题地使用 ArrayDataProvider 来实现您的目标。我像一年前一样尝试过这种方法,结果令人失望。 SQL_CALC_FOUND_ROWS 在 InnoDB 卷上运行缓慢并使用更多资源。如果您运行大量网站 - 保持快速并监控资源使用的最佳方式,而不是精确度。是的,在那个时候插入的机会真的很小。所有东西都在网格上测试了 40m 记录表。
-
还有一件事,告诉我或解释 SQL_CALC_FOUND_ROWS 在哪里比 COUNT() 更快。根据我在高负载数据库上的测试/经验(现在在 yii2 上管理每个 db 约 500m 记录的站点),我从未见过 SQL_CALC_FOUND_ROWS 快,尤其是。在 InnoDB 上,它比 MyISAM 更适合大数据。
-
@ineersa 我不会假装知道更快的事实,这就是为什么我说这取决于应用程序。在发布这个问题之前我也做了一些研究,在那里我获得了一些关于人们说他们的测试结果表明有时
COUNT(*)更快而其他人说SQL_CALC_FOUND_ROWS更快的信息;所以这表明它取决于应用程序。