简体   繁体   中英

Cross Join taking too long

Please see the DDL below:

CREATE TABLE [dbo].[TBX_RRDGenieDeletedItem](
    [DeletedId] [decimal](25, 0) NOT NULL
) ON [PRIMARY]

INSERT INTO TBX_RRDGenieDeletedItem values (90309955000010401948421)

CREATE TABLE [dbo].[dbNicheCIS](
    [OccurrenceID] [decimal](25, 0) NULL,
    [OccurrenceFileNo] [varchar](20) NULL
)

INSERT INTO dbNicheCIS values (90309955000010401948421,'3212')

CREATE TABLE [dbo].[Asset_Table](
    [user_crimenumber] [varchar](4000) NOT NULL
)

INSERT INTO Asset_Table VALUES ('3212; 4512; 34322; 45674; 33221')

The only table I designed was dbNicheCIS. I am trying to find all of the rows in tbx_rrdgeniedeleteditem that are also in Asset_Table using the LIKE statement. Asset_Table contains the OccurrenceFileNo (note that asset table contains occurrencefileno: 3212, which relates to OccurrenceID: 90309955000010401948421) . I have tried this:

Select user_crimenumber from tbx_rrdgeniedeleteditem --asset_table.user_crimenumber 
inner join dbNicheCIS on tbx_rrdgeniedeleteditem.deletedid = dbNicheCIS.OccurrenceID
cross join asset_table
where deletedid like '903%' and asset_table.user_crimenumber like '%' + occurrencefileno + '%'

It works, but it takes hours to run. Is there a better way to approach it rather than a cross join?

You can use INNER JOIN and also you can eliminate LIKE for the number comparison like below

Select user_crimenumber from tbx_rrdgeniedeleteditem
inner join dbNicheCIS 
on tbx_rrdgeniedeleteditem.deletedid = dbNicheCIS.OccurrenceID
inner join asset_table
on CAST(LEFT([DeletedId], 3) AS [decimal](25, 0)) =903 
and asset_table.user_crimenumber like '%' + occurrencefileno + '%'

you can make use of the in operator in this case

SELECT * FROM TBX_RRDGenieDeletedItem
WHERE DeletedId IN (
SELECT DISTINCT OccurrenceID FROM dbNicheCIS
INNER JOIN Split(...) ON ...)

Updated: You can create a custom split function which will split the values into a temp table and then do the join.

You need to index your tables to get faster query response.

CREATE INDEX [IX_dbNicheCIS_OccurrenceID] ON [dbNicheCIS]
([OccurrenceID] ASC, [OccurrenceFileNo] ASC)

CREATE INDEX [IX_TBX_RRDGenieDeletedItem_DeletedId] ON [dbo].[TBX_RRDGenieDeletedItem]
([DeletedId] ASC)

Creating such indexes replaces "Table scan" in query execution plan with faster "Index scan" and "Index seek". But you cannot solve like '%' + occurrencefileno + '%' problem with simple indexes. There you will have to use full text indexes . After you define fulltext index on asset_table.user_crimenumber , you can use following query

SELECT user_crimenumber 
FROM tbx_rrdgeniedeleteditem  di --asset_table.user_crimenumber 
JOIN dbNicheCIS dnc
ON di.deletedid = dnc.OccurrenceID
CROSS JOIN asset_table at
WHERE di.deletedid like '903%' 
AND CONTAINS(at.user_crimenumber, occurrencefileno)

But it is a bad practice to store your occurrencefileno list as a varchar value delimited with semicolons. If you were the author of this database design, you should have tried to normalize the data, so that you got one row for every occurrencefileno and not a string like '3212; 4512; 34322; 45674; 33221' '3212; 4512; 34322; 45674; 33221' '3212; 4512; 34322; 45674; 33221' .

You can also create as a first step before querying a normalized version of asset_table.user_crimenumber and then use this table with normal indexes as a base for your further queries.

To split your asset_table.user_crimenumber fields you can use the Fn_Split() function as mentioned in this answer .


There is also option using the fnSplit to rewrite your query this way:

SELECT user_crimenumber 
FROM tbx_rrdgeniedeleteditem  di --asset_table.user_crimenumber 
JOIN dbNicheCIS dnc
ON di.deletedid = dnc.OccurrenceID
INNER JOIN (
    SELECT at.user_crimenumber, f.item FROM asset_table at 
    CROSS APPLY dbo.fnSplit(at.user_crimenumber,';') f   ) at
ON at.item=dnc.occurrencefileno
WHERE di.deletedid like '903%'

If you create fnSplit as CLR in C# as described here you may get even faster results. But it will not speed up your query magically.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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