首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >按性能随机排序

按性能随机排序
EN

Stack Overflow用户
提问于 2011-07-13 22:14:10
回答 4查看 3K关注 0票数 5

按随机顺序获取top n行的最好方法是什么?

我使用如下查询:

代码语言:javascript
运行
复制
Select top(10) field1,field2 .. fieldn
from Table1
order by checksum(newid())

上面查询中的问题是,随着表大小的增加,它将变得越来越慢。它将始终执行完全聚集索引扫描,以按随机顺序查找top(10)行。

有没有其他更好的方法呢?

EN

Stack Overflow用户

发布于 2018-09-20 21:27:19

这个问题已经问了7年了,而且还没有被接受的答案。但当我在选择随机行时搜索SQL性能时,它的排名很高。但目前的答案似乎都不能给出一个简单,快速的解决方案,在大型表的情况下,所以我想补充我的建议。

假设:

  • 主键是数字数据类型(每行通常为int / +1 )
  • 主键是聚集索引
  • 表有很多行,应该只选择其中的几行

我认为这是相当普遍的,所以它在很多情况下都会有帮助。

给定一组典型的数据,我的建议是

  1. 查找最大和最小
  2. 选择一个随机数并检查该数是否为表中的有效id
  3. 根据需要重复

这些操作都应该非常快,因为它们都在聚集索引上。只有在最后,才会读取剩余的数据,方法是根据主键列表选择一组数据,这样我们就只拉入我们实际需要的数据。

示例(MS SQL):

代码语言:javascript
运行
复制
--
-- First, create a table with some dummy data to select from
-- 

DROP TABLE IF EXISTS MainTable
CREATE TABLE MainTable(
    Id int IDENTITY(1,1) NOT NULL,
    [Name] nvarchar(50) NULL,
    [Content] text NULL
)
GO

DECLARE @I INT = 0
WHILE @I < 40
BEGIN
    INSERT INTO MainTable VALUES('Foo', 'bar')
    SET @I=@I+1
END
UPDATE MainTable SET [Name] = [Name] + CAST(Id as nvarchar(50))

-- Create a gap in IDs at the end
DELETE FROM MainTable
    WHERE ID < 10

-- Create a gap in IDs in the middle
DELETE FROM MainTable
    WHERE ID >= 20 AND ID < 30

-- We now have our "source" data we want to select random rows from



--
-- Then we select random data from our table
-- 

-- Get the interval of values to pick random values from
DECLARE @MaxId int
SELECT @MaxId = MAX(Id) FROM MainTable

DECLARE @MinId int
SELECT @MinId = MIN(Id) FROM MainTable

DECLARE @RandomId int
DECLARE @NumberOfIdsTofind int = 10

-- Make temp table to insert ids from
DROP TABLE IF EXISTS #Ids
CREATE TABLE #Ids (Id int)

WHILE (@NumberOfIdsTofind > 0)
BEGIN
    SET @RandomId = ROUND(((@MaxId - @MinId -1) * RAND() + @MinId), 0)
    -- Verify that the random ID is a real id in the main table
    IF EXISTS (SELECT Id FROM MainTable WHERE Id = @RandomId)
    BEGIN
        -- Verify that the random ID has not already been inserted
        IF NOT EXISTS (SELECT Id FROM #Ids WHERE Id = @RandomId)
        BEGIN
            -- It's a valid, new ID, add it to the list.
            INSERT INTO #Ids VALUES (@RandomId)
            SET @NumberOfIdsTofind = @NumberOfIdsTofind - 1;
        END
    END
END

-- Select the random rows of data by joining the main table with our random Ids   
SELECT MainTable.* FROM MainTable
INNER JOIN #Ids ON #Ids.Id = MainTable.Id
票数 1
EN
查看全部 4 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/6680310

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档