简体   繁体   English

使用Like(SQL Server 2005/8)从组合的列中查询数据

[英]Querying data from a combination of columns using Like (SQL Server 2005/8)

I have a table with around 15 columns which can be queried with different combination. 我有一张约有15列的表格,可以用不同的组合查询。 The table columns for instance is UserID, LocationID, DepartmentID, CoOrdinate1, CoOrdinate2, CoOrdinate3...CoOrdinate15. 例如,表列为UserID,LocationID,DepartmentID,CoOrdinate1,CoOrdinate2,CoOrdinate3 ... CoOrdinate15。

To speed up the retrieval of combination of data we have created a Computed field where we are storing the values of these columns in the format :UserID::LocationID::DepartmentID::CoOrdinate1:...:CoOrdinate15: - a sample value would look like :1:100:20:22:39:94:29:..:9: 为了加快数据组合的检索速度,我们创建了一个计算字段,该字段以以下格式存储这些列的值:UserID :: LocationID :: DepartmentID :: CoOrdinate1:​​...:CoOrdinate15:-一个样本值将看起来像:1:100:20:22:39:94:29:..:9:

While this is fine for retrieving data where the index key matches ( = operator) we are exploring the best method to fetch combinations. 虽然这对于在索引键匹配( =运算符)的情况下检索数据是很好的,但我们正在探索获取组合的最佳方法。

For instance if the user queries for UserID = 1 and CoOrdinate = 15 we plan to build a Like condition '%:1::%::%::%::%::%::%::%::%::15:%'. 例如,如果用户查询UserID = 1且CoOrdinate = 15,我们计划构建一个类似条件'%:1 ::%::%::%::%::%::%::%::%: :15:%'。

SQL Server is doing an Index Scan to retrieve the data. SQL Server正在执行索引扫描以检索数据。 From a performance point of view - is there a better way to approach this problem. 从性能的角度来看,有没有更好的方法来解决此问题。

From the information supplied, it looks as though there are up to 15 numerical coordinates for each record on the existing table. 从提供的信息来看,现有表上的每个记录似乎最多有15个数字坐标。

Which means that the existing table is not properly normalised. 这意味着现有表未正确归一化。

I strongly recommend restructuring the existing table to be more like: 我强烈建议将现有表重组为:

UserID
LocationID
DepartmentID
CoOrdinate Number
CoOrdinate Value

(Alternatively, retain the existing table without the CoOrdinate fields and add a new table with the UserID, LocationID, DepartmentID combination replaced by the key field from the existing table.) (或者,保留不包含CoOrdinate字段的现有表,并添加一个新表,其中UserID,LocationID,DepartmentID组合由现有表中的键字段替换。)

This should allow for much simpler and more efficient querying of data - indexes on numeric fields are much smaller and faster-accessed than on long string fields. 这应该允许更简单,更有效的数据查询-与长字符串字段相比,数字字段上的索引要小得多且访问速度更快。

That computed field makes no sense at all. 该计算字段完全没有意义。 LIKE queries are very slow. LIKE查询非常慢。 You can have multiple indexes on a table, including multiple columns as required. 您可以在一个表上具有多个索引,并根据需要包括多个列。 You'll be much better off relying on SQL Server's own indexing than trying to roll your own. 与依靠自己的索引相比,依靠SQL Server自己的索引会更好。

Try simple approach, I'm wrapping it into SP: 尝试简单的方法,我将其包装到SP中:

CREATE PROC Find
@UserId int,
@LocationId int,
....
@CoOrdinate15 int
WITH RECOMPILE
AS
BEGIN
  SET NOCOUNT ON;

  SELECT [what you need]
  FROM YourTable
  WHERE 
      (@UserId IS NULL OR UserId = @UserId) 
  AND (@LocationId IS NULL OR LocationId = @LocationId)
  ...
  AND (@CoOrdinate15 IS NULL OR CoOrdinate15  = @CoOrdinate15)
END

RECOMPILE causes Sql Server's optimizer to finely adopt each call to SP taking into account NULL-valued parameters and to choose the right index for every call RECOMPILE使Sql Server的优化程序考虑到NULL值的参数来精确地采用对SP的每次调用,并为每次调用选择正确的索引

No. Leading wildcard LIKE searches will always be rubbish. 不能。领先的通配符LIKE搜索永远都是垃圾。

Do you really need complete exhaustive search flexibility? 真的需要完整的详尽搜索灵活性吗?

If you are looking for '%:1::%::%::%::%::%::%::%::%::15:%' then you should search correctly with WHERE x=1 and y=15 and add appropiate indexes. 如果要查找'%:1::%::%::%::%::%::%::%::%::15:%' ,则应使用WHERE x=1 and y=15正确搜索, WHERE x=1 and y=15并添加适当的索引。

let me sum this up: 让我总结一下:

  • when query a table, in your where clause you can have an arbitrary combination of the columns 查询表时,在where子句中您可以具有任意组合
  • you could create an individual index on each column, but only one of them would be used for your query, as normal b-tree indexes cannot be combined 您可以在每列上创建一个单独的索引,但是由于查询中无法合并普通的b树索引,因此只能使用其中一个进行查询
  • you could create composite indexes on certain combination of columns but these indexes would only be used by those queries that have a where clause that matches the columns in the composite index; 您可以在某些列组合上创建组合索引 ,但是这些索引将仅由具有where子句与组合索引中的列匹配的查询使用; also, having many wide composite indexes would incur big maintenance overhead 同样,拥有许多广泛的综合索引将导致大量的维护开销
  • Since you want to filter against arbitrary combination of the columns in your queries, composite indexes are not an option: you cannot create a composite index for all possible combination of columns 由于要过滤查询中列的任意组合,因此复合索引不是一种选择:您无法为所有可能的列组合创建复合索引

In general, the solution to this problem is having bitmap indexes on each columns, because bitmap indexes can be combined. 在一般情况下,解决了这个问题在具有位图索引每个列,因为位图索引可以组合。 Unfortunately SQL Server does not support bitmap indexes but I've heard it has some similar feature. 不幸的是,SQL Server不支持位图索引,但是我听说它具有一些类似的功能。 I suggest you look into that: 我建议您调查一下:

http://msdn.microsoft.com/en-us/library/bb522541.aspx (This article discuss the usage of bitmap indexes when joining tables, but dont let that confuse you, they can be useful in your use case as well, when you query a single table.) http://msdn.microsoft.com/zh-cn/library/bb522541.aspx (本文讨论了在连接表时使用位图索引的方法,但不要让它感到困惑,它们在您的用例中也很有用,当您查询单个表时。)

If you insist on the computed field you should construct it such a way: 如果坚持计算字段,则应采用以下方式构造它:

"field1=value1;field2=value2;....;fieldn=valuen"

that is 那是

"UserID=123;LocationID=34;DepartmentID=2;CoOrdinate1=56;..."

You would define a full text index on the computed field 您将在计算字段上定义全文索引

For instance if the user queries for UserID = 1 and CoOrdinate = 15 your where clause would be 例如,如果用户查询UserID = 1且CoOrdinate = 15,则where子句为

WHERE CONTAINS(computed_field, "UserID=1" AND "CoOrdinate=15") 在哪里包含(computed_field,“ UserID = 1”和“ CoOrdinate = 15”)

You will have to take care of properly indexing "=" and numbers when you define your index. 定义索引时,必须注意正确索引“ =”和数字。 You should treat "=" and numbers as part of the words, so "UserID=1" would be one word in the index. 您应将“ =”和数字视为单词的一部分,因此“ UserID = 1”将是索引中的一个单词。

建立以where 1=1开头的where子句,并将每个相关部分附加为and xx_field = 'value'and xx_field like '%value%'

Erland Sommarskog对您的案例进行了很好的分析: T-SQL中的动态搜索条件

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM