Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/27.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
SQL从数百万条记录中选择记录_Sql_Sql Server_Sql Server 2008 - Fatal编程技术网

SQL从数百万条记录中选择记录

SQL从数百万条记录中选择记录,sql,sql-server,sql-server-2008,Sql,Sql Server,Sql Server 2008,我需要根据日期范围从包含500万条记录的表中选择记录。返回结果需要19秒。只有ID字段是主键,日期字段没有索引 所选记录计数仅为500。如何优化查询 select * from productdetail where createddate >= '01 Jan 2016' and createddate <= '05 mar 2016' 非常感谢您的建议/帮助。将createddate作为非聚集索引,并将您的搜索查询放入存储过程中。存储过程将花费更少的时间

我需要根据日期范围从包含500万条记录的表中选择记录。返回结果需要19秒。只有ID字段是主键,日期字段没有索引

所选记录计数仅为500。如何优化查询

 select * 
 from productdetail 
 where createddate >= '01 Jan 2016' 
      and createddate <= '05 mar 2016'
非常感谢您的建议/帮助。

将createddate作为非聚集索引,并将您的搜索查询放入存储过程中。存储过程将花费更少的时间检索数据

希望这有帮助
感谢..

通常,没有更好的方法,搜索非索引列必须执行线性搜索。 但在您的情况下,如果主键是自动递增的,并且createddate表示记录创建日期,这意味着更大的主键,更晚的createddate日期/时间记录,则可以手动对主键执行二进制搜索

下面是一个示例,ID为从0开始索引的自动递增主键。每个选择语句只涉及ID,因此查询速度很快。 请注意,仅当createddate相对于主键ID排序时,此选项才有效:


是否有特定的原因阻止您为createddate编制索引?您可能希望使用您的搜索技能,进一步了解查询优化、索引、分区以及如何处理大型表。您的问题和提供的信息过于广泛,无法提供一个好的答案。考虑到硬件、设置、其他应用程序运行和基础设施,每个数据库服务器都有点不同。我们可以提出解决方案,但你必须自己做研究才能找到最好的解决方案。只需19秒就可以搜索500万条没有索引的记录!?!一点也不坏。有什么能证明你的观点吗?为什么SPs在数据检索方面比独立查询更快?****检查此链接您得到了答案。您阅读了答案吗?这是一个神话,性能总是相当于报价。是的,准备执行与SPs不同,SPs可能更快,但与数据检索相比,您节省的时间实际上可以忽略不计,只有在重用查询时才能看到性能提高。还有一种叫做参数中毒的东西,它可能会导致SPs中的查询性能差。。。。。。。。。。。。。。。。。。检查它您谈论的是数据检索,而不是引擎中准备查询的方式。尽管如此,关键是:即席SQL和存储过程与这个答案在治疗上没有区别。是的,嵌入到存储过程中的查询有一个优点,即它们只在优化器中运行一次。但是,与实际检索数据所需的时间相比,查询所节省的少量时间可以忽略不计。索引seek well参数中毒没有区别,请从一个临时查询和一个sp中了解它,该sp用于具有相同参数的相同查询。搜索时间是一样的。你说的二进制搜索是什么意思?如何在SELECT语句中进行二进制搜索?有一个很大的假设,createdate的顺序必须与主键的顺序相同。如果是这样,则可以使用T-SQL While语句对主键执行二进制搜索,以查找createdate在周期内的主键值的边界。生成的主键范围也是createdate的主键范围。您能详细说明一下吗?二进制搜索在内存中的数组上工作,您需要随机访问,以便在每次迭代中跳转并将范围减半。如何在不将整个表加载到内存中的情况下执行二进制搜索,并首先排除执行此操作的原因?@BrankoDimitrijevic如果主键按1自动递增,它可以用作索引,就像按索引列在数组查询中搜索一样。添加了一个T-SQL示例。@很酷,但是。。。在一台真正的生产服务器上有多少?为了好玩-是的,做得好。
DECLARE @lowerBoundID INT
DECLARE @upperBoundID INT
DECLARE @maxID INT
SELECT @maxID = MAX(ID) FROM productdetail
SET @lowerBoundID = 0
SET @upperBoundID = @maxID

IF (SELECT createddate FROM productdetail WHERE ID = @lowerBoundID) > '05 mar 2016' OR (SELECT createddate FROM productdetail WHERE ID = @upperBoundID) < '01 Jan 2016'
BEGIN
    DECLARE @first INT
    DECLARE @last INT
    DECLARE @middle INT

    SET @first = 0
    SET @last = @maxID
    SET @middle = (@first + @last) / 2
    WHILE @last - @first > 1
    BEGIN
        IF (SELECT createddate FROM productdetail WHERE ID = @middle) < '01 Jan 2016'
            SET @first = @middle
        ELSE
            SET @last = @middle

        SET @middle = (@first + @last) / 2
    END

    IF (SELECT createddate FROM productdetail WHERE ID = @first) < '01 Jan 2016'
        SET @lowerBoundID = @last
    ELSE
        SET @lowerBoundID = @first


    SET @first = 0
    SET @last = @maxID
    SET @middle = (@first + @last) / 2
    WHILE @last - @first > 1
    BEGIN
        IF (SELECT createddate FROM productdetail WHERE ID = @middle) > '05 mar 2016'
            SET @last = @middle
        ELSE
            SET @first = @middle

        SET @middle = (@first + @last) / 2
    END

    IF (SELECT createddate FROM productdetail WHERE ID = @last) > '05 mar 2016'
        SET @upperBoundID = @first
    ELSE
        SET @upperBoundID = @last

    SELECT * FROM productdetail WHERE ID >= @lowerBoundID AND ID <= @upperBoundID
END