【问题标题】:Making pivot use index from underlying table of view从基础视图表中制作枢轴使用索引
【发布时间】:2018-06-21 09:52:50
【问题描述】:

我的基础表如下所示:

   ----------------------------
   | Id | Type  |Value      |
   ----------------------------
   | 1  |Name   |Michael    |
   | 1  |Age    |20         |
   | 2  |Name   |John       |
   | 3  |Name   |Smith      |
   | 5  |Age    |25         |
   ----------------------------

我在“类型”、“值”列上创建了一个索引。 (编辑:基于 cmets 的附加值)

我探索了几个选项来给我一个透视图。像这样的:

   ------------------------
   | Id |Name   |Age      |
   ------------------------
   | 1  |Michael|20       |
   | 2  |John   |         |
   | 3  |Smith  |25       |
   ------------------------

Sql1(使用数据透视):

CREATE View vw AS 
SELECT  
    ID
    NAME,
    AGE
FROM
(
    SELECT 
       ID,
       TYPE,
       VALUE
    FROM table
) AS SourceTable
PIVOT
(
    MAX(VALUE)
     FOR TYPE IN ([Name],[Age])
) piv

Sql2(条件聚合)

CREATE View vw AS 
SELECT
   Id,
   [Name]= MAX(CASE WHEN [TYPE]='Name' THEN VALUE END),
   [Age] = MAX(CASE WHEN [TYPE]='Age' THEN VALUE END)
FROM
   table
GROUP BY
   Id

当我运行如下查询时:

SELECT * FROM vw WHERE vw.Name = 'Michael'

我看到执行计划正在对主键 (id) 使用索引扫描。 有什么方法可以使它工作,以便它使用我在“类型”列上创建的索引?

编辑: 我本身没有平面表的原因是因为对于每个 id,我最终可能会得到大约 100 个字段。并且应该可以根据任何字段进行搜索。因此,如果我能够让系统使用 (Type, Value) 上的索引,我希望这样的设计可能会有所帮助

【问题讨论】:

  • 在您的示例中,ID 不是主键,因为 ID 是重复的。 Sql1 查询也不会产生相同的结果。你为 Type 建立了什么样的索引?
  • 对不起,我错过了。我的主键是 (ID, Type) 组合。至于Type上的其他索引,它是Non-Clustered Index。
  • 既然你没有任何过滤条件,你为什么期望一个索引被使用呢?聚簇索引扫描是您所需要的,也是您得到的。
  • @Alex,没有任何过滤条件是什么意思。我的过滤条件适用于新的 Pivot 列(WHERE vw.Name = 'Michael')。基于上述评论,我为(类型,值)添加了一个非聚集索引。我希望在添加子句 WHERE vw.Name = 'Michael' 时使用它而不是主键扫描
  • 尝试在视图上创建索引,而不是在表上

标签: sql sql-server sql-server-2008 pivot


【解决方案1】:

如果你想使用 SEEK,你可以改进你的代码:

SELECT * FROM vw WHERE vw.Name = 'Michael'

在 WHERE 条件下用 ID 替换 Name(或添加 ID 过滤器)

SELECT * FROM vw WHERE vw.Name = 'Michael' and ID = 1

或者只是

SELECT * FROM vw WHERE ID = 1

如果您在执行期间没有该 ID 值,则可以在该查询之前获取它或使用子查询/连接。您可能需要为 Type 和 Value 创建一个索引,以便快速找到该 ID。

【讨论】:

  • 如果我想找到 Name = 'Michael' 的记录,我不知道这会有什么帮助。如果我得到了 id,那么我不需要运行这个查询。另一件事是我可以将基础表本身设计成看起来像视图。但我希望该表有大约 100 列,并且数据应该可以在其中任何一个上搜索。为每列添加索引会显着减慢插入和更新速度。
  • 100 列什么?你的意思是 Type1 Value1 Type2 Value 2... Type100 Value100?如果您只想拥有 100 个值/100 种类型(因此您仍然只有 ID/Value/Type 列),则此答案涵盖了这一点。
  • 我的意思是我的表可以设计两种方式 Id、Type、Value 或 Id、Name、Age、AddressCity、AddressState....Salary(100 条记录)第一种方法意味着每 1 条记录 100 条ID。第二种方法意味着每个 id 有 1 条记录。我可能想根据姓名或年龄或薪水或城市等进行搜索。
  • 我的意思是,如果你决定实施第一种方法,我的方法就行了。子查询将找到所有具有搜索字符串的 ID,然后如果查询优化器认为索引搜索更好(当没有太多具有相同搜索字符串的 ID 时),它将使用索引搜索。如果表很大,还可以通过[类型]添加分区,这样当你搜索特定类型时,它只会查找一个分区,其他分区将被淘汰
猜你喜欢
  • 2019-07-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-05-30
  • 1970-01-01
  • 1970-01-01
  • 2016-11-07
相关资源
最近更新 更多