我有一个静态数据集,它将一系列数字与某些元数据相关联,例如
+--------+--------+-------+--------+----------------+
| 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行是相当微不足道的,而且我可以做得不多,但我们假设行数可以大几个数量级。
答案 0 :(得分:1)
如果您通常同时搜索min
和max
,则(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。当然是有空间成本。但查询将更容易保持。
我记得有一次我需要计算一些sin
和cos
来计算距离,所以我只创建一次计算列。
+--------+--------+-------+--------+----------------+----------+
| 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强制范围内的唯一性,并防止数据库存储重叠范围。