如果我有列密钥的多列索引:col_1,col_2和col_3
如果查询在WHERE子句中具有以下条件,则查询是否会使用此索引: col_1 = any_value AND col_3 = any_value
这是另一个例子: 如果索引有10列,并且列键按此顺序排列: col_1,col_2,....,col_10 然后,我运行了这个查询: 从X中选择col_1,col_2,...,col_10 WHERE col_1 = any_value AND col_5 = any_value AND col_10 = any_value
和我的问题:在这种情况下是否会使用索引?
答案 0 :(得分:0)
新答案,因为我现在对您的问题更加清楚
不,不会使用索引。只有在col_1
或col_1
/ col_2
或col_1
/ col_2
/ col_3
上查询时,索引才会 被使用。使用查询的执行计划进行检查。您的多列索引的顺序很重要:请查看此问题,以便围绕此主题Multiple Indexes vs Multi-Column Indexes
如果您认为您更有可能在col_1
和col_3
上进行查询,为什么不在这两列上创建多列索引?
答案 1 :(得分:0)
可能会被使用。这取决于许多因素,主要是您的数据(以及有关您的数据的统计数据)和您的查询。
TL / DR;您需要根据自己的数据和自己的查询对此进行测试。可以使用索引。
您应该尝试一下您拥有或期望拥有的数据。创建一些测试数据非常容易,您可以在其中测试查询并尝试不同的索引。您可能还需要重新考虑索引中列的顺序,col_1真的是索引中第一个最好的列吗?
下面是一个非常具体的场景,我们只能从中得出结论,有时可以在与您类似的场景中使用索引。
请考虑以下情况;该表包含1M行,并且(a,b,c)上只有一个非聚簇索引。请注意,D列中的值非常大。
下面的前4个查询使用了索引,只有第5个查询没有。
为什么?
Sql Server需要弄清楚如何在读取最少量数据时完成查询。有时,即使查询过滤器与索引不完全匹配,SQL Server也更容易读取索引而不是表。
在查询1和2中,查询实际上会对索引进行搜索,这非常好。它知道A列是执行Seek on的良好候选者。
在查询3和4中,它需要扫描整个索引以查找匹配的行。它仍然使用索引。
在查询5中,SQL Server意识到扫描实际表而不是索引更容易。
IF OBJECT_ID('tempdb..#peter') IS NOT NULL DROP TABLE #peter;
CREATE TABLE #peter(a INT, b INT, c VARCHAR(100), d VARCHAR(MAX));
WITH baserows AS (
SELECT * FROM master..spt_values WHERE type = 'P'
),
numbered AS (
SELECT TOP 1000000
a.*, rn = ROW_NUMBER() OVER(ORDER BY (SELECT null))
FROM baserows a, baserows b, baserows c
)
INSERT #peter
( a, b, c, d )
SELECT
rn % 100, rn % 10, CHAR(65 + (rn % 60)), REPLICATE(CHAR(65 + (rn % 60)), rn)
FROM numbered
CREATE INDEX ix_peter ON #peter(a, b, c);
-- First query does Seek on the index + RID Lookup.
SELECT * FROM #peter WHERE a = 55 AND c = 'P'
-- Second Query does Seek on the index.
SELECT a, b, c FROM #peter WHERE a = 55 AND c = 'P'
-- Third query does Scan on the index because the index is smaller to scan than the full table.
SELECT a, b, c FROM #peter WHERE c = 'P'
-- Fourth query does a scan on the index
SELECT a, b, c FROM #peter WHERE b = 22
-- Fifth query scans the table and not the index
SELECT MAX(d) FROM #peter
在SQL Server 2014上测试。
答案 2 :(得分:0)