【问题标题】:Indexing and optimization of where clause based on datetime field基于日期时间字段的where子句的索引与优化
【发布时间】:2015-07-20 11:31:06
【问题描述】:

我有一个包含超过一百万行集数据的数据库。当我执行这个查询需要几个小时,主要是由于 pageIOLatch_sh。目前没有索引。你能在where子句中建议可能的索引吗?我相信它应该在日期时间,因为它在 where 和 order by 中使用,如果是的话,使用哪个索引。

if(<some condition>)
BEGIN
select <some columns>
From <some tables with joins(no lock)>

WHERE

    ((@var2 IS NULL AND a.addr IS NOT NULL)OR
        (a.addr LIKE @var2 + '%')) AND
    ((@var3 IS NULL AND a.ca_id IS NOT NULL) OR
        (a.ca_id = @var3)) AND
    b.time >= @from_datetime AND b.time <= @to_datetime AND
    (
            (
                b.shopping_product IN ('CX12343', 'BG8945', 'GF4543') AND
                b.shopping_category IN ('online', 'COD')
            )
            OR
            (
                b.shopping_product = 'LX3454' and b.sub_shopping_list in ('FF544','GT544','KK543','LK5343')
            )
            OR 
            (
                b.shopping_product = 'LK434434' and b.sub_shopping_list in ('LL5435','PO89554','IO948854','OR4334','TH5444')
            )

            OR 
            (
                b.shopping_product = 'AZ434434' and b.sub_shopping_list in ('LL54352','PO489554','IO9458854','OR34334','TH54344')
            )
    )AND

    ORDER BY 
        b.time desc
ELSE
BEGIN
select <some columns>
From <some tables with joins(no lock)>
where <similar where as above with slight difference>

【问题讨论】:

  • 请说明您使用的是哪个 DBMS。您同时标记了 - mysql 和 sqlserver
  • 微软 SQL 服务器 2005
  • 如果你没有索引,我猜问题是连接,你没有包含在问题中。
  • 首先对这些 :shopping_product 和 shopping_category sub_shopping_list 进行索引,然后您可以尝试日期,然后查看执行计划。 (或者最好在时间列上创建分区)
  • OR 很难优化。尝试将条件拉入连接。可以去掉一个或者用 isnull(@var3, a.ca_id) = a.ca_id

标签: sql-server indexing query-optimization


【解决方案1】:

那好吧,

我说“首先对这些:shopping_product 和 shopping_category sub_shopping_list 进行索引,然后您可以尝试在日期上,然后查看执行计划。(或者最好在时间列上创建分区)”

我正在研究 oracle,但基础是一样的。

您可以在该 cols 上创建 3 个不同的索引:shopping_product、shopping_category、sub_shopping_list。或者您可以为这 3 个列创建 1 个复合索引。关键是您需要检查哪个执行计划对您最有效。 哦,这里是一个 .ca_id 列(差点忘了),你也需要一个索引。

对于日期列,我认为您最好创建一个分区而不是索引。

总结,两种方式: - 创建 4 个不同的索引 (shopping_product,shopping_category,sub_shopping_list, ca_id) ,在日期列上创建一个范围类型的分区 - 创建1个复合索引(shopping_product,shopping_category,sub_shopping_list)和1个普通索引(ca_id),在日期列上创建一个范围类型的分区

【讨论】:

    【解决方案2】:

    如果您要处理这种大小的表,您可能应该了解索引。这不是一个简单的过程。在整理出您需要的索引时,JOIN 操作很重要。读这个。 http://use-the-index-luke.com/

    与此同时,如果您的日期范围具有高度选择性(也就是说,如果

     b.time >= @from_datetime AND b.time <= @to_datetime
    

    选择数据库中相当小的一部分行)您应该尝试以下复合索引。

    b.shopping_product, b.time
    

    如果没有帮助,请尝试

    b.time
    

    本身。这个想法是构建您的索引,以便服务器可以执行range scan. 在不了解您的整个查询的情况下,没有什么可以提供的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-12-11
      • 2020-09-16
      • 2022-01-09
      • 1970-01-01
      • 2010-12-29
      • 2019-09-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多