1

非常に大きなデータベースでIDを検索する必要があります。IDは次のとおりです。

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

データベースには数百のテーブルがあり、大きなテーブルには数百万の行があります。

過去2、3か月以内に日付を絞り込むことができますが、それだけです。このような検索を絞り込む方法についての手がかりを探しています。

私が興味を持っていることの1つは、LIKE検索の使用が役立つかどうかです。

つまり、次のようなことをするのに役立ちますか

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

ヒント/提案は大歓迎です。データベースはリモートでアクセスされているため、これは課題の一部です

4

3 に答える 3

2

テキストフィールドを使用していますが、同様の目的で数年前に作成したこのスクリプトがあります。適格な列が検出され、それらの列で値が検索されます。非決定論的なスコープがあるため、このようなことよりもうまくできない場合があります。

uniqueidentifier 列を含めるように少し調整することもできます (それが実際のデータ型である場合)。または、like 検索の代わりに equal を使用することもできます。

これが定期的に再利用するものである場合は、共通のテーブルまたは列のリストをフィードして、これらのものを見つけることができるため、見つけるのにそれほど時間がかかりません.

/*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 行が影響を受けています」と表示されている場所)。

于 2012-07-26T19:37:41.700 に答える
2

まず第一に、whoel データベースから特定の値が必要な理由は何ですか。値を見つけるのは 1 回限りの作業のように見え、それに基づいて何らかのアクションを実行します。しかし、時間とリソースを消費する可能性があります。

とにかく、ガイド列のように見えます。すべての guid 列にインデックスがない限り、高速化する方法はありません。

とにかく、ここに guid 列を持つすべてのテーブルで select ステートメントを生成する小さなクエリがあります (これが varchar 列の場合、各テーブルの各列にクエリを作成する必要があり、それを書くことができるため、非常に困難です)私はそれが効率的であるとは思わない)。

ただし、最も重要なことは、出力が以下に基づいて順序付けられることです。guid 列にインデックスと先行キーがある場合、それらのテーブルが最初にリストされます。次に、クエリが最小限のリソースを使用するように、データページに基づいてテーブルが一覧表示されます。したがって、guid 値が最初のいくつかのテーブルにある場合は、非常に高速になります。最後のテーブルにある場合は、テーブルのサイズに基づいて時間がかかるため、多くの時間がかかる可能性があります。

また、このクエリでカーソルを宣言してから、ステートメントを1つずつ実行し、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
于 2012-07-26T19:23:11.537 に答える
1

DESIRED_IDの一部を設定しIndexます。

このテーブルに何もない場合Index、データベースエンジンが実行Table scanし、「016」のようなものかどうかを確認し、適切reads every rowに実行すると常にパフォーマンスが大幅に向上することを確認しますDESIRED_IDindexing

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')
于 2012-07-26T19:14:44.840 に答える