我们有一个网络应用程序,可以帮助组织生物实验(用户描述实验和上传实验数据)。在主页面中,我们显示前10个实验,然后是下一个上一个下一个1 2 3 .. 30。
我告诉我如何有效地计算总数和分页。目前:
select count(id) from experiments; // not very efficient in large datasets
但是在处理大型数据线时这是如何扩展的? 200.000。我试图将随机实验导入到表中,但它仍然表现得相当不错(对于300.000次实验,为0.6秒)。
我想到的另一个选择是添加附加表statistics (column tableName, column recordsCount)
。因此,在每次插入表experiments
之后,我会在recordsCount
中增加statistics
(这意味着插入一个表并更新其他表,当然使用sql事务)。反之亦然,删除语句(recordsCount - )。
对于分页,最有效的方法是执行where id > last_id
,因为sql当然使用索引。还有其他更好的方法吗?
如果要过滤结果,例如select * from experiment where name like 'name%'
,表statistics
的选项失败。我们需要将总计数计为:select count(id) from experiment where name like 'name%'
。
应用程序是使用Laravel 3开发的,以防万一。
我想开发总是执行相同的分页。记录计数不得影响分页或记录总数。
答案 0 :(得分:0)
请查询如下:
CREATE PROCEDURE [GetUsers]
(
@Inactive Bit = NULL,
@Name Nvarchar(500),
@Culture VarChar(5) = NULL,
@SortExpression VarChar(50),
@StartRowIndex Int,
@MaxRowIndex Int,
@Count INT OUTPUT
)
AS
BEGIN
SELECT ROW_NUMBER()
OVER
(
ORDER BY
CASE WHEN @SortExpression = 'Name' THEN [User].[Name] END,
CASE WHEN @SortExpression = 'Name DESC' THEN [User].[Name] END DESC
) AS RowIndex, [User].*
INTO #tmpTable
FROM [User] WITH (NOLOCK)
WHERE (@Inactive IS NULL OR [User].[Inactive] = @Inactive)
AND (@Culture IS NULL OR [User].[DefaultCulture] = @Culture)
AND [User].Name LIKE '%' + @Name + '%'
SELECT *
FROM #tmpTable WITH (NOLOCK)
WHERE #tmpTable.RowIndex > @StartRowIndex
AND #tmpTable.RowIndex < (@StartRowIndex + @MaxRowIndex + 1)
SELECT @Count = COUNT(*) FROM #tmpTable
IF OBJECT_ID('tempdb..#tmpTable') IS NOT NULL DROP TABLE #tmpTable;
END