我有一张没有主键的表(或者甚至没有复合键)。
该表用于存储食品店的时段(营业时间和可用时间的食物供应时间)。我们将表格称为“business_hours”,主要字段如下所示。
例如,如果商店A在周一上午9点至下午1点和下午5点至晚上10点开放,则此场景的business_hours表中将有两条记录。
-----------------------------------------------
| shop_id | day | type | start_time | end_time
-----------------------------------------------
| 1000 | 1 | open | 09:00:00 | 13:00:00
-----------------------------------------------
| 1000 | 1 | open | 17:00:00 | 22:00:00
-----------------------------------------------
当我查询这个表时,我将始终将shop_id用作where子句中的第一个条件。
前:
SELECT COUNT(*) FROM business_hours WHERE shop_id = 1000 AND day = 1 AND type = 'open' AND start_time <= '13.29.00' AND end_time > '13.29.00';
为“shop_id”应用索引是足够的或“日”&amp; “type”字段也应编入索引?
如果你能解释索引的确如何运作,也会更好。
答案 0 :(得分:1)
是的,您要在此列上创建聚簇索引(shop_id,day,type)。我创建了一个如上所述的索引:
Create clustered index Ix on business_hours (shop_id,day,type)
使用此索引,您的选择查询如上所述:
SELECT COUNT(*) FROM business_hours with (index (Ix)) WHERE shop_id = 1000 AND day = 1 AND type = 'open' AND start_time <= '13.29.00' AND end_time > '13.29.00';
你得到的结果很快,但是有一个主键而不是创建的表 聚集索引并创建非聚集索引
答案 1 :(得分:1)
如果您不更新记录然后使用聚集索引,则取决于您的可用性 在
<div class="popup">
<h2>Here i am</h2>
<a class="close" href="#">×</a>
</div>
因为聚簇索引沿着B树遍历并将整行存储在节点本身上,所以搜索速度很快。但是更新记录是内存成本有效的,因为它将整行从内存中移出,为同一记录创建新条目。
OR ELSE
如果您正在更新记录,那么非聚集索引。
如果您创建仓库,则使用列存储索引
为了更好地理解你可以转到这些链接
http://kodeweave.sourceforge.net/editor/#8d7733f82faf240e0edcb6739c5d1a1a
http://www.programmerinterview.com/index.php/database-sql/clustered-vs-non-clustered-index/
http://www.patrickkeisler.com/2014/04/what-is-non-clustered-columnstore-index.html
请回复。
答案 2 :(得分:1)
这取决于您应指定的几个因素:
更多的是思考:一些服务每小时会有数千个新记录插入,旧记录将每晚存档,并且每晚都会从该表创建报告。在这种情况下,您可能不希望创建多个索引,因为它们会降低插入速度。
另一方面,如果您的表会增长并且变化缓慢并且许多用户将针对它运行查询,则需要使用适当的索引来加速查询。
如果可以,请尝试创建大多数查询可以从中受益的群集唯一主键。如果您拥有构成某个时间轴的数据,并且大多数查询将使用日期时间条件(例如from - to)获取数据范围,则最好在聚簇索引中包含datetime - 您将获得最快的查询性能。
所以这样的事情会为你提到的选择给你最好的表现。 (但您不能为一个商店存储重复的营业时间并输入)
CREATE TABLE Business_hours
( shop_id INT NOT NULL
, day INT NOT NULL
--- other columns
, CONSTRAINT Business_hours_PK
PRIMARY KEY (shop_id, day, type, start_time, end_time) -- your clustered index
)
只需在SELECT中使用的字段(所有字段或其中一些最常用的字段)创建索引,也会加快查询速度:
CREATE INDEX BusinessHours_IX ON business_hours (shop_id,day,type, start_time, end_time);
群集和非群集之间的区别在于群集索引会影响存储在磁盘上的db记录的顺序。
您可以使用EXPLAIN在数据库中查找缺失的索引,请参阅this answer。
更多细节this blog。
答案 3 :(得分:1)
决定反对主键意味着允许以下内容:
| shop_id | day | type | start_time | end_time +---------+-----+--------+------------+--------- | 1000 | 1 | open | 09:00:00 | 13:00:00 | 1000 | 1 | open | 09:00:00 | 13:00:00 | 1000 | 1 | open | 17:00:00 | 22:00:00 | 1000 | 1 | closed | 17:00:00 | 22:00:00
因此,您可以拥有可能导致奇怪查询结果的重复条目,甚至可以在同一时间范围内关闭商店和。 (但是,我们都知道,即使使用主键,您仍然需要一个插入前触发器来检测范围重叠,例如12:00-15:00与13:00- 16:00,并抛出一个错误。 - 我希望有一些内置的范围检测,所以我们可以说,(shop_id, day, range(start_time, end_time))
上有一个唯一的索引。)
关于您的问题:如果您的数据库构建良好,则您已在shop_id
上拥有外键。只要您足够快地考虑查询,就不需要任何其他索引。
一旦您认为需要加快速度,就可以根据需要添加复合索引。这通常是慢查询的WHERE
子句中所有列的索引。如果仍然不够,请添加GROUP BY
子句中的列(如果有)。下一步是添加HAVING
子句的列,如果有的话。接下来是ORDER BY
子句的列。最后一步是在SELECT
子句中添加所有列,这将为您提供覆盖索引,即查询所需的所有数据都将在索引中,因此表本身不必是再访问了。
但如上所述:只要您没有性能问题,就不必添加任何复合索引。
答案 4 :(得分:1)
要确定必须在数据库表中索引哪些字段,您需要观察每个查询的行为,发送到表索引是在应用程序和数据之间提供有效访问路径的方法。索引提供了访问路径,因此查询要求数据到数据库,它将知道去哪里检索数据。
这里有一些官方的Microsoft文档
群集索引 聚簇索引将实际表数据页存储在叶级,并且表数据在密钥周围进行物理排序。 一个表只能有一个聚簇索引,并且在创建此索引时,还会发生以下事件: •表格数据重新排列。 •创建新索引页面。 •重建数据库中的所有非聚簇索引。 因此,有许多磁盘I / O操作以及系统和内存资源的广泛使用。如果计划创建聚簇索引,请确保可用空间至少等于表中数据量的1.5倍。额外的可用空间确保您有足够的空间来有效地完成操作。
非聚集索引 在非聚簇索引中,叶级别的页面包含一个书签,该书签告诉SQL Server在哪里可以找到与索引中的键对应的数据行。如果表具有聚簇索引,则书签指示聚簇索引键。如果表没有聚簇索引,则书签是实际的行定位器。 创建非聚簇索引时,SQL Server会创建所需的索引页,但不会重新排列表数据。
专业人士推荐的索引方法由三个阶段组成:监控,分析,然后实现索引。这意味着您需要在运行查询时观察数据库的行为,然后努力获得最佳性能
SQL Server使用此操作来获取数据:
表扫描:读取整个堆,并且很可能将所有数据传递给辅助过滤器操作
索引扫描:读取聚簇索引或非聚簇索引的整个叶级(每一行)。索引扫描操作可能会过滤行并仅返回符合条件的行,或者它可能会将所有行传递给另一个过滤操作,具体取决于条件的复杂程度。可能会或可能不会订购数据。
索引寻求: 使用索引查找特定的行数据,并仅返回有序列表中的选定行
一旦您知道可以运行查询并使用“显示估计执行计划”选项https://msdn.microsoft.com/en-us/library/ms191194.aspx并分析性能 我建议阅读这篇文章 “SQL SERVER - 索引寻求比。索引扫描“ http://blog.sqlauthority.com/2007/03/30/sql-server-index-seek-vs-index-scan-table-scan/和https://msdn.microsoft.com/en-us/library/dn673537.aspx