【问题标题】:Improving Query performance - T-SQL提高查询性能 - T-SQL
【发布时间】:2018-03-12 14:38:53
【问题描述】:

我有一个已经按“日期时间”列排序的表。因为当它被插入时,我存储了 UTC 日期,所以它是有序的。这是一张人满为患的桌子。因此,如果可能的话,我正在尝试提高查询性能。

当我使用 WHERE columnDateTime > dateToSearch 时,返回行需要很长时间。由于我的表已经由columnDateTime 订购,我可以做些什么来提高这个查询性能。例如,当一个表按cod 排序并且您尝试搜索cod > 40 时,T-SQL 优化将在找到 cod = 41 时停止搜索并返回表的其余部分,因为它知道表按该索引排序。这是一种可以告诉 T-SQL 我的表已经被 columnDateTime 排序的方法吗?

【问题讨论】:

  • (1) 您使用的是mysql 还是SQL ServerT-SQL 是 Microsoft 的 SQL 版本。 (2) 在关系数据库中,“表按……排序”的概念是不准确的。这些表不是而且根本不能订购。但是,它们确实有索引。在考虑性能时,了解所有索引的确切详细信息也很重要。 (3) 您的问题太模糊无法回答:“太长”有多长?说“人口众多”意味着什么都没有! (4) 确切的查询很重要! 阅读:How to Ask
  • @RafaelAndrade 数据 IS NOT 在关系数据库中“排序”。它仅由查询中的 ORDER BY 子句排序。
  • 如果是SQL Server,可以通过聚簇键/聚簇索引有一个逻辑(非物理)顺序,尽管与所有性能转向一样——查询+模式+查询计划需要提供指导.如果没有聚集索引,则表是一个堆,虽然您可能认为存在基于插入的顺序,但 SQL Server 没有可以依赖的顺序。
  • 如果您以严格的时间顺序插入行,并且该列永远不会更新,并且大多数查询都会对其进行过滤,那么它是一个很好的候选者(非唯一) 聚集索引。当然,您也可以在其上创建一个常规索引。如果没有索引,SQL Server 只会生成有关列中值分布的统计信息——这些是一些帮助,但不如正确的索引那么多。它不能利用你认为存在的任何顺序,因为它不能保证存在一个。
  • @AnthonyHancock 也许您应该确保自己理解正确地了解聚集索引的概念,然后再声称我在告诉人们“信息不正确” ?聚集索引仍然有分散在磁盘各个页面中UNORDERED的数据,可以使用聚集索引以特定顺序检索数据。优化器根据查询、索引和表统计信息来决定是否以那种方式使用聚集索引。

标签: sql performance tsql


【解决方案1】:

按顺序插入数据并不代表按顺序保存。无需过于技术化并获得更快的性能:

  • 在该列上创建一个CLUSTERED INDEX。这要求您的表上没有其他聚集索引,并且它没有PRIMARY KEY(或者它有NONCLUSTERED,这不是默认值)。使用聚集索引,引擎将在使用> datetimeValue 过滤时执行索引扫描(不是全表扫描),并且不需要访问数据的其他页面,因为聚集索引离开 数据。

  • 在该列上创建一个NONCLUSTERED INDEX。对这个子句没有限制(至少在这种情况下),但是对于与您的过滤日期匹配的每个匹配项,引擎将需要访问具有请求列的另一个页面,除非您在创建索引时INCLUDE 他们。请记住,包含的列会增加索引的大小,并且需要额外的维护任务,例如,当包含的列被修改时。

除此之外,您应该检查您的查询计划;如果您有连接、函数调用或附加条件,SQL 引擎可能不会使用索引,即使它们存在。有很多事情可能会使查询运行缓慢,您必须发布完整的查询执行计划(作为开始)以检查详细信息。

您可以使用此查询来检查您的表是否已经有索引:

DECLARE @table_name VARCHAR(200) = 'YourTableName'

SELECT
     SchemaName = SCHEMA_NAME(t.schema_id),
     TableName = t.name,
     IndexName = ind.name,
     IndexType = CASE ind.index_id WHEN 0 THEN 'Heap' WHEN 1 THEN 'Clustered' ELSE 'Nonclustered' END,
     Disabled = ind.is_disabled,
     ColumnOrder = ic.index_column_id,
     ColumnName = col.name,
     ColumnType = y.name,
     ColumnLength = y.max_length,
     ColumnIncluded = ic.is_included_column
FROM 
    sys.indexes ind
    INNER JOIN sys.index_columns ic ON  ind.object_id = ic.object_id and ind.index_id = ic.index_id 
    INNER JOIN sys.columns col ON ic.object_id = col.object_id and ic.column_id = col.column_id 
    INNER JOIN sys.tables t ON ind.object_id = t.object_id 
    INNER JOIN sys.types y ON y.user_type_id = col.user_type_id
WHERE 
     t.is_ms_shipped = 0 AND
     t.name = @table_name
ORDER BY
    SchemaName,
    t.name, 
    ind.name, 
    ic.index_column_id 

您需要确保至少有一个索引包含您的datetimeColumnColumnOrder = 1,并且它没有被禁用。如果它已经存在,那么您的问题出在其他地方,如果没有更多详细信息,我们将无法提供太多帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-05-26
    • 2016-09-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多