SQL Server:查询性能(搜索 200 万行)

Dea*_*mas 7 sql-server-2005 database-design

有一个有趣的 SQL 大师在那里。现在这个搜索只需要几秒钟,但它非常密集,必须有更好的方法。可能是我期望太高了?

简单的假期搜索应用程序。200 万假期。分页/排序大约 600,000 行。

这是表的架构

CREATE TABLE [dbo].[Holiday](
        [Id] [int] NOT NULL,
        [PropertyId] [int] NOT NULL,
        [Price] [int] NOT NULL,
        [Rating] [int] NOT NULL,
        [Country] [char](2) NOT NULL,
        [ResortId] [int] NOT NULL,
        [DepartureAirport] [char](3) NOT NULL,
        [DestinationAirport] [char](3) NOT NULL,
        [DepartureDate] [datetime] NOT NULL,
        [Basis] [char](2) NOT NULL,
        [Duration] [int] NOT NULL,

     CONSTRAINT [PK_Holiday] PRIMARY KEY CLUSTERED ([Id] ASC)
  )
Run Code Online (Sandbox Code Playgroud)

如您所见,非常简单。我们有属性、价格、持续时间、出发/目的地机场等。现在,提供的字段越多,搜索速度就越快。如果我有出发机场、财产和日期,那么搜索速度非常快。但是,如果我只有一个国家而不是其他任何东西,则需要处理大量数据。

使用我的表格的这个CSV 导出,总共有 200 万行,大约 666k 仅国家代码为 FR,这是我的例子。

这是搜索查询。它返回两个表。第一个是摘要,因此符合您的条件的假期总数以及有多少独特的属性。第二个表包含搜索的实际结果。

--Build a temp table, and store everything we need in it
CREATE TABLE #Pricing (PropertyId int, Duration int, HolidayId int, Rating int, Price int, StartDate datetime, PropertyRow int);

INSERT INTO #Pricing
  SELECT 
    PropertyId, Duration, [Id], [Rating], [Price], DepartureDate,
    ROW_NUMBER() OVER (PARTITION BY PropertyId ORDER BY Price ASC) as PropertyRow
  FROM 
    dbo.Holiday
  WHERE 
    DepartureDate > GETDATE() AND Country = 'FR'

--Get a total number of holidays, and total number of properties
SELECT 
    COUNT(*) AS TotalHolidaysCount, 
    COUNT(DISTINCT PropertyId) AS PropertyCount
FROM 
    #Pricing

--Build the final table, which will contain all the holidays we actually want to return
DECLARE @FinalResults TABLE (HolidayId int, RowNumber int);

INSERT INTO 
    @FinalResults
  SELECT 
    HolidayId, RowNumber
  FROM
    (SELECT 
         PropertyRow, HolidayId, 
         ROW_NUMBER() OVER (order by (CASE WHEN StartDate <= '01/Apr/2013' THEN 1 ELSE 0 END) ASC, [Price] ASC) as RowNumber
     FROM  
        #Pricing 
     WHERE 
        PropertyRow = 1) as SearchResults
WHERE 
    (RowNumber > (10 * (1 - 1)) and RowNumber <= (1 * 10))
ORDER BY 
    RowNumber;

SELECT
     *
FROM
    @FinalResults
    INNER JOIN dbo.Holiday ON HolidayId = Holiday.Id

DROP TABLE #Pricing
Run Code Online (Sandbox Code Playgroud)

现在,我可以研究索引,这显然会提高性能。但让我担心的是临时表的惊人使用。这当然不应该是它的做法吗?花 5 秒钟来搜索最终是微量的数据。使用它们的唯一原因是以后需要引用数据。

是否值得运行查询两次,而不是将所有数据存储在内存中?一次又一次地将超过 25% 的表选择到内存中似乎是一种浪费。

任何有用的反馈将不胜感激。不是在寻找“答案”,只是一些帮助。

非常感谢,院长

小智 2

如果没有索引,则每次运行搜索查询时,都必须搜索所有 200 万条记录才能找到 65 万个“FR”实例。通过索引,数据库基本上可以直接访问它们。即使您按原样保留搜索查询,我认为适当的索引也会提高速度。

就临时表而言,我真的不明白为什么不能在最终结果查询中作为子表来完成。除此之外,我认为临时表对于与数据库或用户池的持久连接更有用。如果您只是创建临时表并立即销毁它......那么它基本上只是被用作子查询。

更新: M_M 在对此答案的评论中提出了很好的观点。然而,我仍然认为,如果大多数活动不只是以国家/地区为唯一标准,那么指数会更好。对我来说(只是我的意见),这取决于“FR”子集本身需要的频率,没有其他标准。否则,可以在大多数搜索中使用索引。