2011-10-22 47 views
0

我需要从表中随机选择一行。起初,我写了SP这样的:从表中获取随机行 - 尝试优化查询 - SQL Server

SELECT * FROM 
    (SELECT TOP 1 
    * 
    FROM PeopleTales PT 
    LEFT JOIN PeopleTalesCategories PTC ON PT.CategoryAn = PTC.Analit 
    WHERE LEN(PT.Text) > 900 
    ORDER BY NEWID() 
    ) t1 

这不是很好的实时统计:

平均总执行时间= 200

接下来,我试图手动采取行:

WITH CTE_t 
AS 
(
     SELECT 
     ROW_NUMBER() OVER (ORDER BY PT.Analit) AS RowNumber, 
     * 
     FROM PeopleTales PT 
     LEFT JOIN PeopleTalesCategories PTC ON PT.CategoryAn = PTC.Analit 
     WHERE LEN(PT.Text) > 900 
) 


SELECT * FROM CTE_t 
WHERE CTE_t.RowNumber = 1 + ABS(CHECKSUM(NewId())) % (SELECT COUNT(CTE_t.RowNumber) FROM CTE_t) 

这是由执行时间好一点,但有时我有0行,有时结果1,2甚至3行! +我知道,使用CTE并不是很好。这不是决定。

平均总执行时间= 60

所以,下一步:

SELECT * FROM (
    SELECT 
     ROW_NUMBER() OVER (ORDER BY PT.Analit) AS RowNumber, 
     * 
    FROM PeopleTales PT 
    LEFT JOIN PeopleTalesCategories PTC ON PT.CategoryAn = PTC.Analit 
    WHERE LEN(PT.Text) > 900 
    ) t1 
WHERE t1.RowNumber = (SELECT 1 + ABS(CHECKSUM(NewId())) % (SELECT 
                  COUNT(Analit) 
                  FROM PeopleTales 
                  WHERE LEN(Text) > 900)) 

每次我只有一个排,及其与总执行时间确定。

平均总执行时间= 60

那么,是不是更多的方式来采取随机行或优化我的查询?

Thx很多的回应。

回答

1

表中有多少行,是否可以修改您的模式?一个问题是所有的选择都基于LEN(Column),所以SQL Server不能有效地使用索引。

你可能想要考虑的是一个计算列,并在其上放置一个索引。喜欢的东西:

ALTER TABLE PeopleTales ADD TextLength AS LEN(PT.Text) 
GO 
CREATE INDEX IX_PeopleTales_TextLen ON PeopleTales (Text, CategoryAN) 
GO 

我包括CategoryAN所以有联接由索引纯粹达成(并意味着SQL Server不具备做一个书签或键查找)。

然后,显然,更改您的查询,以便WHERE LEN(PT.Text) > 900变成WHERE TextLength > 900

+0

1.有2000行,是的 - 我可以修改架构。是的,它有助于将平均执行时间降低到45-50。但是,MB在查询中出现错误/不正确的地方,有什么可以重写的? – FSou1

+0

你的执行计划是什么样的?这应该是您的第一个停靠港,因为它会显示花费时间。另外,您的目标查询时间是多少? –