【问题标题】:Speed up SQL queries by converting data to XML?通过将数据转换为 XML 来加速 SQL 查询?
【发布时间】:2011-02-22 10:46:21
【问题描述】:

我正在接管一个非常小的利基分类广告网站(可能每天 5 个新条目),该网站运行良好,直到 Google 和 Bing 成功。每个类别、子类别和广告都存储在数据库 (MS SQL 2005) 中,因此他们抓取的每个页面都会遇到这些查询并占用 CPU。

为了解决这个问题,我的老板希望我将所有数据卸载到 XML 文件中并改为查询这些文件(哇?)。我认为这必须比必要的工作多得多,但作为一名业余 DBA,除了调整查询、使用存储过程、创建适当的索引等之外,我没有任何可靠的选择......

XML 参数有什么依据吗?你会怎么做才能避开这个蜘蛛问题?

类别:

SELECT Category.CatID, Category.CatName, Category.Remove, CategorySub.SubCatID, CategorySub.SubCatName, CategorySub.TitleText, CategorySub.ShowPrice, CategorySub.ShowLocation, CategorySub.Remove
FROM Category INNER JOIN CategorySub ON Category.CatID = CategorySub.CatID
WHERE (((Category.Remove)=0) AND ((CategorySub.SubCatID)=" & intSubCatID & ") AND ((CategorySub.Remove)=0))

子类别:

SELECT CategorySub.CatID, CategorySub.SubCatName, CategorySub.SubCatOrder, CategorySub.SubCatID, CategorySub.Remove FROM CategorySub
WHERE (((CategorySub.CatID)=" & intCatID & ") AND ((CategorySub.Remove)=0))
ORDER BY CategorySub.SubCatOrder

广告:

SELECT Ad.AdID, Ad.ModifiedDate, Ad.CatID, CategorySub.SubCatName, Ad.Title, Ad.ShortDesc, Ad.Price, Ad.Location, Count(Pictures.PictureID) AS CountOfPictureID
FROM (Ad INNER JOIN CategorySub ON Ad.SubCatID = CategorySub.SubCatID) LEFT JOIN Pictures ON Ad.AdID = Pictures.AdID
WHERE (((Ad.SubCatID)=" & intSubCatID & ") AND ((Ad.Activated)<>0) AND ((Ad.Remove)=0))
GROUP BY Ad.AdID, Ad.ModifiedDate, Ad.CatID, CategorySub.SubCatName, Ad.Title, Ad.ShortDesc, Ad.Price, Ad.Location
ORDER BY Ad.ModifiedDate DESC

【问题讨论】:

    标签: sql xml


    【解决方案1】:
    • 您可以阻止蜘蛛访问您的网站或某些网页(通过使用 robots.txt)。
    • 或者您可以在索引您时运行不同的查询(无广告)(通过检查 User-Agent 标头)

    【讨论】:

      【解决方案2】:

      其中哪些查询有问题?阅读它们时我唯一突然想到的是,您的广告查询在 group by 子句中有很多内容 - 这可能会占用大量 tempdb,然后它必须按其他内容对结果进行排序。由于进行聚合的唯一原因似乎是将图片折叠成一行,而且您似乎只关心那里是否有图片,请考虑将其更改为:

      SELECT Ad.AdID, ..., Ad.Location,
             (SELECT COUNT(*) FROM Pictures WHERE Pictures.AdID = Ad.AdID) AS CountOfPictureID
      FROM Ad
      WHERE ...
      ORDER BY ...
      

      或者:

      SELECT Ad.AdID, ..., Ad.Location,
             CASE WHEN EXISTS (SELECT COUNT(*) FROM Pictures WHERE Pictures.AdID = Ad.AdID)
                  THEN 1 ELSE 0 END AS PictureExists
      FROM Ad
      WHERE ...
      ORDER BY ...
      

      如果您需要获取第一张图片的一些数据,您可以使用 OUTER APPLY,但这不需要产生您已经获得的相同结果。

      实际上,除非您有 很多 数据(您没有提到绝对数量),否则这类查询应该不成问题。另一件要考虑的事情是旧广告是否保留在主广告表中(如果是,请考虑编写一个流程,在它们过期后将它们归档;或者创建一个仅包含广告的 AdID 值的附加表显示和 INNER JOIN 与广告)。当然,请查看导致速度变慢的主要查询的计划……您是否有足够的日志记录以查看哪些查询占用了时间?你能证明是 SQL 查询减慢了页面速度还是其他东西占用了时间?

      缓存变化不大的数据有一些好处。例如,您的标题和副标题是否与您的广告一样频繁地更改?我希望会有很大的不同。某种数据库外缓存——XML 文件,memcached——可用于删除一遍又一遍地获取相同旧数据的查询,代价是需要一种方法来确保被重用的数据是可以接受的-to-date(例如,至少每 X 分钟刷新一次)。

      我们自己,我们不得不更改一堆浏览页面以从本地文档数据库而不是 RDBMS 获取数据,因为有问题的 RDBMS 不能很好地将几个正交的非选择性标准组合在一起(不是同时无论如何,运行网站的其余部分)。我犹豫要不要使用当下的流行词“NoSQL”,但这就是它的本质(尽管理论上问题并不在于使用 SQL 数据库,而只是我们对查询的规划不够好)。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-01-13
        • 2020-12-18
        • 1970-01-01
        • 1970-01-01
        • 2021-07-17
        • 1970-01-01
        • 1970-01-01
        • 2015-06-02
        相关资源
        最近更新 更多