如何加快 SQL 服务器中的随机选择
How to speedUp Random selecting in SQL Server
我有一个 table 用于 phone 个数字,如下所示:
ID PhoneNumber Enabled GrupID CountryID
----------- -------------------- ------- ------ -----------
10444 ***001000999 1 NULL 1
10445 ***001000998 1 NULL 1
10446 ***001000994 1 NULL 1
10447 ***001000990 1 NULL 1
10448 ***001000989 1 NULL 1
这个 table 有 68992507 行。
我想从中 select 一些随机的 phone 号码。
我可以通过这个存储过程得到我的随机数查询:
这里我 select 随机数,插入到 @table
然后更新 selected 数字。
CREATE proc [dbo].[Mysp_GetRandom]
@countryid int,
@count int
as
declare @tbl table([ID] [int] ,
[PhoneNumber] [nchar](20) NOT NULL,
[Enabled] [bit] NULL,
[GrupID] [tinyint] NULL,
[CountryID] [int] NULL)
INSERT INTO @tbl
SELECT TOP (@count) *
FROM tblPhoneNumber
WHERE CountryID = @countryid
AND GrupID is null
ORDER BY binary_checksum(ID * rand())
UPDATE tblPhoneNumber
SET GrupID = 1
WHERE ID IN (SELECT ID FROM @tbl)
SELECT * FROM @tbl
问题是查询到运行需要很长时间。例如,此查询需要 12:30 分钟 ...
DECLARE @return_value int
EXEC @return_value = [dbo].[Mysp_GetRandom]
@countryid = 14, @count = 3
SELECT 'Return Value' = @return_value
我有一个索引 table :
CREATE NONCLUSTERED INDEX [NonClusteredIndex-20150415-172433]
ON [dbo].[tblPhoneNumber] ([CountryID] ASC)
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF,
SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF,
ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
执行计划如下:
谢谢...
看看你的查询计划,第一个 INSERT 语句几乎占了 100% 的时间,其中 70% 是排序。由于您已经在使用 BINARY_CHECKSUM
,因此您无能为力。可能是 table 以足够随机的方式填充,以便从随机偏移量开始获取连续的行,如下所示:
SELECT ID FROM tblPhoneNumber WHERE CountryID = @countryid
AND GrupID is null ORDER BY ID OFFSET CONVERT(int,
rand()*(select count(*) from tblPhoneNumber)-@count-1)
ROWS FETCH NEXT @count ROWS ONLY
将 grupID 添加到索引键列并在 NC 索引 NonClusteredIndex-20150415-172433 的 include 子句中添加其他必需的列。
执行计划已经为您提供了添加缺失索引的相同提示。
P.S如果对您有帮助,请设为答案。
您应该按条款替换订单。
您可以创建相当随机的 ID:
declare @count int = 100
; with ids(id, hex) as (
Select 1, convert(bigint, convert(varbinary, '0x'+right(newid(), 6), 1 ))
Union all
Select id+1, convert(bigint, convert(varbinary, '0x'+right(newid(), 6), 1 ))
From ids
Where id+1 <= @count
)
Select * from ids
Option (MAXRECURSION 0)
然后您可以使用您的 table ID 加入 table。
您应该检查您的索引(其他人提到的)并在 phone Id 上添加索引。
我有一个 table 用于 phone 个数字,如下所示:
ID PhoneNumber Enabled GrupID CountryID
----------- -------------------- ------- ------ -----------
10444 ***001000999 1 NULL 1
10445 ***001000998 1 NULL 1
10446 ***001000994 1 NULL 1
10447 ***001000990 1 NULL 1
10448 ***001000989 1 NULL 1
这个 table 有 68992507 行。
我想从中 select 一些随机的 phone 号码。
我可以通过这个存储过程得到我的随机数查询:
这里我 select 随机数,插入到 @table
然后更新 selected 数字。
CREATE proc [dbo].[Mysp_GetRandom]
@countryid int,
@count int
as
declare @tbl table([ID] [int] ,
[PhoneNumber] [nchar](20) NOT NULL,
[Enabled] [bit] NULL,
[GrupID] [tinyint] NULL,
[CountryID] [int] NULL)
INSERT INTO @tbl
SELECT TOP (@count) *
FROM tblPhoneNumber
WHERE CountryID = @countryid
AND GrupID is null
ORDER BY binary_checksum(ID * rand())
UPDATE tblPhoneNumber
SET GrupID = 1
WHERE ID IN (SELECT ID FROM @tbl)
SELECT * FROM @tbl
问题是查询到运行需要很长时间。例如,此查询需要 12:30 分钟 ...
DECLARE @return_value int
EXEC @return_value = [dbo].[Mysp_GetRandom]
@countryid = 14, @count = 3
SELECT 'Return Value' = @return_value
我有一个索引 table :
CREATE NONCLUSTERED INDEX [NonClusteredIndex-20150415-172433]
ON [dbo].[tblPhoneNumber] ([CountryID] ASC)
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF,
SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF,
ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
执行计划如下:
谢谢...
看看你的查询计划,第一个 INSERT 语句几乎占了 100% 的时间,其中 70% 是排序。由于您已经在使用 BINARY_CHECKSUM
,因此您无能为力。可能是 table 以足够随机的方式填充,以便从随机偏移量开始获取连续的行,如下所示:
SELECT ID FROM tblPhoneNumber WHERE CountryID = @countryid
AND GrupID is null ORDER BY ID OFFSET CONVERT(int,
rand()*(select count(*) from tblPhoneNumber)-@count-1)
ROWS FETCH NEXT @count ROWS ONLY
将 grupID 添加到索引键列并在 NC 索引 NonClusteredIndex-20150415-172433 的 include 子句中添加其他必需的列。
执行计划已经为您提供了添加缺失索引的相同提示。
P.S如果对您有帮助,请设为答案。
您应该按条款替换订单。
您可以创建相当随机的 ID:
declare @count int = 100
; with ids(id, hex) as (
Select 1, convert(bigint, convert(varbinary, '0x'+right(newid(), 6), 1 ))
Union all
Select id+1, convert(bigint, convert(varbinary, '0x'+right(newid(), 6), 1 ))
From ids
Where id+1 <= @count
)
Select * from ids
Option (MAXRECURSION 0)
然后您可以使用您的 table ID 加入 table。
您应该检查您的索引(其他人提到的)并在 phone Id 上添加索引。