我有两个不同的查询。但它们都在同一个表中并且具有相同的WHERE
子句。所以他们选择了同一行。
查询1:
SELECT HOUR(timestamp), COUNT(*) as hits
FROM hits_table
WHERE timestamp >= CURDATE()
GROUP BY HOUR(timestamp)
查询2:
SELECT country, COUNT(*) as hits
FROM hits_table
WHERE timestamp >= CURDATE()
GROUP BY country
如何提高效率?
答案 0 :(得分:2)
如果这个表格被正确编入索引,那么说实话并不重要,因为你只是查看今天的行。
如果表格索引不正确,无论你做什么,这些查询的表现都会很糟糕。
您的WHERE timestamp >= CURDATE()
子句意味着您需要在timestamp
列上添加索引。在您的某个查询中,GROUP BY country
显示覆盖(timestamp, country)
上的索引的化合物将是一个很好的帮助。
因此,单个复合索引(timestamp, country)
将满足您问题中的两个查询。
让我们解释一下这是如何运作的。要查找今天的记录(或者实际上任何以特定timestamp
值开头和结尾的记录)并按国家/地区对它们进行分组,并对它们进行计数,MySQL可以通过以下步骤来满足查询:
timestamp
匹配的第一条记录。 O(log n)。country
值。country
值并计数。为O(n)。timestamp
范围结束。这种索引扫描操作的速度与ace开发人员团队(MySQL团队)可以通过十年的努力工作一样快。 (你可能无法在星期六下午超越它们。)MySQL用一小部分索引来满足整个查询,所以它背后的表有多大并不重要。
如果你一个接一个地运行其中一个查询,MySQL可能仍然会在RAM缓存中有一些或所有索引数据块,因此它可能不必从磁盘重新获取它们。这将有助于实现更多目标。
您是否看到了示例查询如何通过timestamp
引导?最重要的WHERE
标准选择时间戳范围。这就是为什么我建议的复合索引有timestamp
作为第一列。如果您没有任何带有country
的查询,那么您对该列的简单索引可能毫无用处。
你问你是否真的需要复合覆盖指数。您可能read about how他们的工作并为您自己做出决定。
在选择索引时,显然需要权衡利弊。每个索引都会使INSERT
和UPDATE
的过程变慢,并且可以大大加快查询速度。只有您可以为您的特定应用程序进行权衡。
答案 1 :(得分:0)
由于两个查询都有不同的GROUP BY
子句,因此它们本质上是不同的,无法组合。假设timestamp
字段上已存在索引,则没有直接的方法可以提高效率。
如果数据集很大(1000万或更多行),那么可能在country, timestamp
上制作额外的组合索引时获得一点额外的效率,但这不太可能是可测量的,如果这两个查询直接在另一个查询之后执行,那么MySQL本身的内存缓冲通常可以减轻它的缺失。