在大型数据库中搜索特定 ID?

Posted

技术标签:

【中文标题】在大型数据库中搜索特定 ID?【英文标题】:Searching for a specific ID in a large database? 【发布时间】:2012-07-26 18:26:09 【问题描述】:

我需要在一个非常大的数据库中查找一个 ID。 ID 是:

0167a901-e343-4745-963c-404809b74dd9

数据库有数百个表,大表中有数百万行。

我可以将日期缩小到最近 2 或 3 个月内,但仅此而已。我正在寻找有关如何缩小此类搜索范围的任何线索。

我很好奇的一件事是使用 LIKE 搜索是否有帮助。

也就是说,做类似的事情有帮助吗

select top 10 * 
from BIG_TABLE
where DESIRED_ID like '016%'

非常感谢任何提示/建议。正在远程访问数据库,因此这是挑战的一部分

【问题讨论】:

你定义了哪些索引? 我假设您不知道 id 在哪个表中...您知道它可能在哪个列吗? @mellamokb - 好问题 - 所以有一些查找列(LK_xyz , LK_abc ) - 这些是正确的索引 @Randy - 我知道,但桌子很大,所以没有多大帮助 好吧——问题是如何加快查询速度?或者首先要写什么查询? 【参考方案1】:

我有几年前为类似目的而构建的这个脚本,尽管它带有文本字段。它找到符合条件的列,然后在这些列中搜索值。由于您的范围是不确定的,因此您可能无法比这样做得更好。

您可能需要稍微调整一下以包含唯一标识符列 - 如果这实际上是数据类型 - 或者使用相等而不是类似搜索。

如果这是您要定期重复使用的东西,您可以向它提供一个常用表或列的列表以在其中查找这些东西,这样就不会花很长时间找到东西。

/*This script will find any text value in the database*/
/*Output will be directed to the Messages window. Don't forget to look there!!!*/

SET NOCOUNT ON
DECLARE @valuetosearchfor varchar(128), @objectOwner varchar(64)
SET @valuetosearchfor = '%putYourGuidHere%' --should be formatted as a like search 
SET @objectOwner = 'dbo'

DECLARE @potentialcolumns TABLE (id int IDENTITY, sql varchar(4000))

INSERT INTO @potentialcolumns (sql)
SELECT 
    ('if exists (select 1 from [' +
    [tabs].[table_schema] + '].[' +
    [tabs].[table_name] + 
    '] (NOLOCK) where [' + 
    [cols].[column_name] + 
    '] like ''' + @valuetosearchfor + ''' ) print ''SELECT * FROM [' +
    [tabs].[table_schema] + '].[' +
    [tabs].[table_name] + 
    '] (NOLOCK) WHERE [' + 
    [cols].[column_name] + 
    '] LIKE ''''' + @valuetosearchfor + '''''' +
    '''') as 'sql'
FROM information_schema.columns cols
    INNER JOIN information_schema.tables tabs
        ON cols.TABLE_CATALOG = tabs.TABLE_CATALOG
            AND cols.TABLE_SCHEMA = tabs.TABLE_SCHEMA
            AND cols.TABLE_NAME = tabs.TABLE_NAME
WHERE cols.data_type IN ('char', 'varchar', 'nvchar', 'nvarchar','text','ntext')
    AND tabs.table_schema = @objectOwner
    AND tabs.TABLE_TYPE = 'BASE TABLE'
    AND (cols.CHARACTER_MAXIMUM_LENGTH >= (LEN(@valueToSearchFor) - 2) OR cols.CHARACTER_MAXIMUM_LENGTH = -1)
ORDER BY tabs.table_catalog, tabs.table_name, cols.ordinal_position

DECLARE @count int
SET @count = (SELECT MAX(id) FROM @potentialcolumns)
PRINT 'Found ' + CAST(@count as varchar) + ' potential columns.'
PRINT 'Beginning scan...'
PRINT ''
PRINT 'These columns contain the values being searched for...'
PRINT ''
DECLARE @iterator int, @sql varchar(4000)
SET @iterator = 1
WHILE @iterator <= (SELECT Max(id) FROM @potentialcolumns)
BEGIN
    SET @sql = (SELECT [sql] FROM @potentialcolumns where [id] = @iterator)
    IF (@sql IS NOT NULL) and (RTRIM(LTRIM(@sql)) <> '')
    BEGIN
        --SELECT @sql --use when checking sql output
        EXEC (@sql)
    END
    SET @iterator = @iterator + 1
END

PRINT ''
PRINT 'Scan completed'

如果这看起来很奇怪,那么脚本正在执行这样的语句

if exists (select 1 from [schema].[table_name] (NOLOCK) 
                    where [column_name] LIKE '%yourValue%')
begin
   print select * from [schema].[table_name] (NOLOCK) 
                    where [column_name] LIKE '%yourValue%'
end

...只需循环替换[schema][table_name][column_name]%yourValue%

它的过滤...

特定架构中的表(可以删除过滤器) 只有表格,没有视图(可以调整) 仅包含搜索值的列 (n)char/(n)varchar/(n)text 数据类型(添加或更改,注意数据类型转换

最后,输出不会进入结果网格。检查消息窗口(您会看到“N 行受影响”)

【讨论】:

哇,非常感谢 - 我需要仔细研究这个!谢谢!! @DavidAndreiNed - 这已经工作了多年。你发现你的案子缺少什么了吗? 扫描返回完成,没有任何列结果。正确指定了所选数据库。 ID 存在于未返回的列中。我想它会扫描表和视图? @DavidAndreiNed - 编辑了更多描述。也许这可以帮助您隔离您正在寻找的项目。 ID 通常不是文本数据类型。【参考方案2】:

首先,您需要从整个数据库中获得特定值的要求是什么。查找值似乎是一次性的工作,并在此基础上采取一些行动。但这可能会耗费时间和资源。

不管怎样,它看起来像一个 guid 列。 除非所有 guid 列都有索引,否则无法加快速度。

无论如何,这里是一个小查询,它将在所有具有任何 guid 列的表上生成选择语句(如果这是一些 varchar 列,那么这非常困难,因为您必须在每个表的每一列 i 上编写查询,您可以写下来,但我不认为这会有效)。

但是,最重要的是输出是基于以下排序的。如果 guid 列上有索引和前导键,那么首先列出这些表。 然后根据数据页列出表,以便查询使用最少的资源。因此,如果您的 guid 值在前几个表中,它将非常快。如果它在最后一个表中,则根据表的大小,这将需要一些时间,因此可能需要很多时间。

另外,在这个查询上声明一个游标,然后一一执行语句,一旦你发现游标循环中的值出来,因为guid是唯一值。这将非常有效。

    select * from (
select 'select '  + ac.name +' from ' + OBJECT_SCHEMA_NAME(ac.object_id) + '.' + OBJECT_NAME(ac.object_id) + ' where ' + ac.name + '=''29490167a901-e343-4745-963c-404809b74dd9''' as querytext
--,*
,isnull(cnt,0) as numberofrows,
ROW_NUMBER() over(order by case when ic.key_ordinal = 0 then 0 else 1 end asc, isnull(si.dpages,si_1.dpages) asc) as rn,isnull(si.dpages,si_1.dpages) datapages
from sys.all_columns ac
inner join sys.all_objects ao on ac.object_id = ao.object_id
left join sys.index_columns ic on ac.object_id=ic.object_id
and ac.column_id =ic.column_id 
left join sys.sysindexes si on ac.object_id = si.id and ic.index_id=si.indid
outer apply (select SUM(rows) from sys.partitions p where ac.object_id = p.object_id and index_id in (0,1) ) a(cnt)
left join sys.sysindexes si_1 on si_1.id =ac.object_id and si_1.indid in (0,1)
where system_type_id =36
and ao.type ='U'
) dta order by rn asc
go

【讨论】:

仍在工作,非常好。我添加了一个 IF EXISTS() PRINT 以获得清晰的结果【参考方案3】:

DESIRED_ID 设置为Index 的一部分。

如果此表上没有Index,数据库引擎将执行Table scanreads every row 来检查DESIRED_ID 是否类似于'016',并确保正确的indexing 始终导致性能显着提高

CREATE INDEX NameIndex ON TableName(ColumnName ASC) 
INCLUDE (ColumnName2) 

实现Index 将搜索从016 到017 或02 或1 的记录。无论它先找到什么,然后停止搜索。

在准备Dynamic query 以在所有表​​中查找示例 GUID 值的数据时。您可以使用以下查询在特定表下的列名中查找数据。

select * from sys.columns where name = 'ColumnName' OBJECT_ID = 
(Select OBJECT_ID From sys.tables Where name = 'Object Name')

【讨论】:

以上是关于在大型数据库中搜索特定 ID?的主要内容,如果未能解决你的问题,请参考以下文章

在 ArrayList 中搜索特定对象

在一个用 JSON 填充的 NSArray 中搜索特定的标题

在一个数组中搜索特定元素并复制另一个数组中的整个对应行

需要帮助使用 pymysql 在数据库中搜索特定值

如何在 MySQL 数据库中搜索特定列名? [复制]

如何在表中的 JSON 数据中搜索特定数据