用于范围查找的SQL Server主键

时间:2015-10-08 16:44:53

标签: sql sql-server

我有一个静态数据集,它将一系列数字与某些元数据相关联,例如

+--------+--------+-------+--------+----------------+
|  Min   |  Max   |Country|CardType|  Issuing Bank  |
+--------+--------+-------+--------+----------------+
| 400011 | 400051 | USA   |VISA    | Bank of America|
+--------+--------+-------+--------+----------------+
| 400052 | 400062 | UK    |MAESTRO | HSBC           |
+--------+--------+-------+--------+----------------+

我希望查找某个任意单值的数据

SELECT * 
FROM SomeTable 
WHERE Min <= 400030 
  AND Max >= 400030

我有大约200k这些范围映射,我想知道SQL Server的最佳表结构?

复合键似乎不正确,因为大多数情况下,查找的值将介于磁盘上存储的两个范围值之间。同样,仅索引第一列似乎没有足够的选择性。

我知道200k行是相当微不足道的,而且我可以做得不多,但我们假设行数可以大几个数量级。

4 个答案:

答案 0 :(得分:1)

如果您通常同时搜索minmax,则(min,max)上的复合键是合适的。引擎会找到min小于X的所有行,然后在这些结果中搜索,以查找max大于Y的行。

如果您仅在min上进行搜索,该索引也会很有用,但如果仅在max上进行搜索则不适用。

答案 1 :(得分:0)

您可以索引第一个数字,然后像这样进行查找:

public void setListOfBooks(List<String> bookList) {
    this.listOfBooks = bookList;
}

或使用select t.*, (select top 1 s.country from static s where t.num >= s.firstnum order by s.firstnum ) country from sometable t;

outer apply

这应该利用select t.*, s.country from sometable t outer apply (select top 1 s.country from static s where t.num >= s.firstnum order by s.firstnum ) s static(firstnum)上的索引。这不会检查第二个数字。如果这很重要,请使用static(firstnum, country)并在子查询外部进行检查。

答案 2 :(得分:0)

如果您为INSERT创建触发器,然后填充相关的计算列country, issuing bank, card-number length

,我相信很容易/更快

最后,您只进行一次计算,而不是每次进行查询时计算200k。当然是有空间成本。但查询将更容易保持。

我记得有一次我需要计算一些sincos来计算距离,所以我只创建一次计算列。

更新后我认为更容易

+--------+--------+-------+--------+----------------+----------+
|  Min   |  Max   |Country|CardType|  Issuing Bank  | TypeID   |
+--------+--------+-------+--------+----------------+----------+
| 400011 | 400051 | USA   |VISA    | Bank of America|    1     |
+--------+--------+-------+--------+----------------+----------+
| 400052 | 400062 | UK    |MAESTRO | HSBC           |    2     |
+--------+--------+-------+--------+----------------+----------+

然后你卡也会创建一个列TypeID

答案 3 :(得分:0)

我会在(Min,Max)上指定主键。查询非常简单:

SELECT *
FROM SomeTable
WHERE @Value BETWEEN Min AND Max

我还要定义一个约束来强制执行Min <= Max。然后我会create a trigger强制范围内的唯一性,并防止数据库存储重叠范围。