将非聚集索引添加到表中以提高性能

时间:2016-10-24 09:14:15

标签: sql-server sql-execution-plan non-clustered-index

我的表结构如下

set statistics io on

SELECT 
    COUNT(featureid), featureid 
FROM
    AIRQUALITYTS2 
WHERE
    FeatureID LIKE 'AS%' 
    AND ParameterID = 'AP2' 
    AND YEAR(MeasurementDateTime) = 2015
GROUP BY 
    FeatureID
ORDER BY 
    FeatureID

执行此查询时:

 CREATE NONCLUSTERED INDEX non_fidpidmdate
     ON [dbo].[AIRQUALITYTS2] ([ParameterID], [FeatureID])
     INCLUDE ([MeasurementDateTime])

我看到逻辑记录 101871 ,查询执行计划是

enter image description here

但是当我在这个表上添加非聚集索引

MeasurementDateTime >= '2004-01-01 00:00:00' 
and MeasurementDateTime <= '2004-12-31 00:00:00' 

当我执行相同的查询时,我看到逻辑记录只读取 4636 ,速度非常快,查询执行计划是

enter image description here

问题1:第二次查询中的逻辑记录较少。

问题2:为什么第一个查询使用第一个图像中显示的聚簇索引扫描虽然它在featureid,ParameterID和MeasurementDateTime上有聚簇索引,但在添加非聚簇索引后它使用索引寻找(非聚集)第二张图像,如图像所示

注意:我已将where子句更改为

@media screen and (max-width: 767px) {
.container {
    width: 100%;
}
.logo {
    background-position: 50% 30px;
}
.banner {
    height: 500px;
}
.banner h1 {
    margin-top: 0px;    
}
.title {
    background-color: #d44137;
    width: 100%;
    margin: 0;
}
.pricing h2 {
    display: none;
}
.pricing {
    width: 100%;
}
.pricing p {
    width: 95%;
}
.pricing-1 {
    margin-left: 0;
}
.pricing-1 p {
    margin-left: 0;
}   
.content {
    width: 100%;
}
.sidebar {
    width: 100%;
}
.testimonials {
    width: 90%;
    float: left;
    margin: 0;
    padding: 10px 5% 10px 5%;
}
.records {
    width: 90%;
    float: left;
    padding: 10px 0 10px 5%;
}
.info {
    width: 90%;
    float: left;
    text-align: justify;
    padding: 10px 0 10px 5%;
}
.info img {
    display: none;
}
.company {
    width: 90%;
    float: left;
    padding: 10px 5% 20px 5%;
}
.video {
    width: 90%;
    float: left;
    margin-left: 5%;
    padding-bottom: 20px;
}
form {
    width: 90%;
    margin: 0 5% 30px 5%;
}
.map {
    width: 90%;
    margin: 0 5% 30px 5%;
}
.contact h1 {
    margin-left: 5%;
}
.footer {
    height: 70px;
}
.copyright {
    font-size: 9pt;
    text-align: center;
}
.social {
    display: none;
}
}

让它变得可靠,但结果仍然相同。

2 个答案:

答案 0 :(得分:2)

对于问题1:由于您的索引涵盖(它包含查询要检索的所有数据以及查询和排序的需要),因此查询可以完全针对索引运行(和它的数据页面并使用搜索,与扫描整个表格(聚集索引扫描 =表扫描)相比,显然从磁盘上加载的页数要少得多数据

不确定你对问题#2的意思....

答案 1 :(得分:1)

  1. 在您创建CREATE TABLE的原始PRIMARY KEY CLUSTERED中,它按照中聚类(存储)的顺序指定要聚类的列
  2. [FeatureID]
    [ParameterID]
    [MeasurementDateTime]
    

    如果您使用包含特定WHERE的{​​{1}}子句运行查询,那么它将能够FeatureID到索引的该部分。

    但是你没有在查询中这样做。 您已使用seek

    查询引擎无法搜索,因为带有尾随通配符WHERE FeatureID LIKE 'AS%' ...的{​​{1}}表示必须扫描以字母LIKE开头的所有FeatureID,然后才能扫描每个树中的节点查看是否存在与%匹配的记录。

    1. 在非聚集索引中,您使用了不同的列顺序:
    2. AS

      当您运行相同的查询时,它可以ParameterID = 'AP2' AND YEAR(MeasurementDateTime) = 2015,因为您已在[ParameterID] [FeatureID] 子句中指定了精确的seek

      订购很重要! SQL索引是 sortof B-Tree数据结构,您无法在不创建多个索引的情况下以不同的顺序物理存储它们(或遍历它们)。创建太多的索引对于数据库来说可能是一个太多的开销,因此创建一个可以帮助大多数查询但不会创建太多的查询。这主要涉及了解经常针对您的数据库运行哪种查询并进行相应调整。