因爲我有很多答案:)我做了一些更多的調查,現在有最後的辦法。
答案是嵌套樹執行快速查詢。
我做了什麼:
創建一個用戶表。
CREATE TABLE [dbo].[actor_users](
[id] [int] NOT NULL,
[manager_id] [int] NULL,
[deputy_id] [int] NULL,
[username] [nvarchar](48) NOT NULL,
[pwd] [nvarchar](40) NULL,
[pwd_url] [char](38) NULL,
[guid] [char](38) NULL,
[deactivated] [smallint] NULL,
[lastname] [nvarchar](48) NULL,
[middlename] [nvarchar](48) NULL,
[firstname] [nvarchar](48) NULL,
[acronym] [nvarchar](16) NULL,
[employee_nr] [nvarchar](16) NULL,
[department] [nvarchar](250) NULL,
[cost_unit] [nvarchar](16) NULL,
[desc] [nvarchar](max) NULL,
[email] [nvarchar](192) NULL,
[sex] [int] NULL,
[group_ids] [nvarchar](4000) NULL,
[picture_id] [int] NULL,
[lcid] [int] NULL,
CONSTRAINT [ct_actor_users] PRIMARY KEY CLUSTERED
([id] ASC) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]) ON [PRIMARY]
創建一個組表。
CREATE TABLE [dbo].[actor_groups](
[id] [int] NOT NULL,
[parent_id] [int] NULL,
[group_name] [nvarchar](max) NULL,
[group_type] [int] NOT NULL,
[group_reference] [int] NOT NULL,
[description] [nvarchar](max) NULL,
[depth] [int] NULL,
[left] [int] NULL,
[right] [int] NULL,
[id_path] [nvarchar](max) NULL,
[name_path] [nvarchar](max) NULL,
CONSTRAINT [ct_actor_groups] PRIMARY KEY CLUSTERED
([id] ASC) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
我用大約10k行的隨機用戶填充了用戶表。
現在我創造了一些隨機樹
-- create some random tree for testing
DECLARE @id int;
DECLARE @name nvarchar(max);
WHILE (SELECT COUNT(*) FROM actor_groups)<1000
BEGIN
SET @id = (SELECT ISNull(MAX(id),0) + 1 FROM actors);
SET @name = 'random_ou' + CAST(NEWID() AS nvarchar(40));
INSERT INTO actor_groups (id, parent_id, group_name, group_type, group_reference, [description], depth, [left], [right], id_path, name_path)
SELECT @id
, (SELECT TOP 1 id FROM actor_groups ORDER BY NEWID()) AS parent_id
, @name group_name
, 3 group_type
, -1 group_reference
, '' [description]
, 0 depth
, 0 [left]
, 0 [right]
, '' id_path
, '' name_path
END
這個我必須更新組嵌套關係後....
-- update tree
WHILE EXISTS (SELECT * FROM actor_groups WHERE depth IS NULL)
UPDATE tr SET
tr.depth = par.depth + 1 ,
tr.id_path = par.id_path + ',' + CAST(tr.id AS nvarchar(255)) ,
tr.name_path = (CASE par.id WHEN 40 THEN '' ELSE par.name_path + '/' END) + tr.group_name
FROM actor_groups AS tr
INNER JOIN actor_groups AS par ON (tr.parent_id = par.id)
WHERE par.depth >=0 AND tr.depth IS NULL
GO
-- left, right nested set
WITH treerows AS
(SELECT actor_groups.*, ROW_NUMBER() OVER (ORDER BY id_path) AS Row FROM actor_groups)
UPDATE actor_groups
SET [left] = tbl.Lft
, [right] = tbl.Rgt
FROM actor_groups
JOIN (SELECT
ER.id,
ER.id_path,
ER.depth,
ER.Row,
(ER.Row * 2) - ER.depth AS Lft,
((ER.Row * 2) - ER.depth) +
(
SELECT COUNT(*) * 2
FROM treerows ER2
WHERE ER2.id_path LIKE ER.id_path + ',%'
) + 1 AS Rgt
FROM treerows ER
) tbl ON tbl.id = actor_groups.id
現在,我做了一些隨機的映射......
-- do some random mappings
DECLARE @map int;
DECLARE @mapuser int;
DECLARE @counter int;
SET @counter = 1;
WHILE @counter<1000
BEGIN
SET @map = (SELECT TOP 1 id FROM actor_groups ORDER BY NEWID())
SET @mapuser = (SELECT TOP 1 id FROM actor_users ORDER BY NEWID())
INSERT INTO actor_mappings ([group_id], [user_id], imported) VALUES (@map, @mapuser, 0)
SET @counter = @counter + 1;
END
所以現在我有一個組和一個用戶表。 用戶填滿10.000個用戶,我的樹有大約1.000個節點。 我確實多次啓動隨機映射SQL,所以我有大約100.000個映射。
我的查詢:
SELECT DISTINCT
m.[user_id] AS luserid
, org.[id] AS lgroupid
, m.imported AS bimported
FROM [test].[dbo].[actor_groups] org
JOIN [actor_groups] org2 ON org2.[left] BETWEEN org.[left] AND org.[right]
JOIN actor_mappings m ON org2.id = m.group_id
查詢周圍700毫秒運行,如果我不縮小它。尋找一個特殊的節點或用戶是在我的測試約150-300毫秒。
分辨率: 這可以使用嵌套集來完成。
使用我的1.000節點更新樹就像1秒一樣,查詢數據時我的表上沒有任何額外的索引也總是低於1秒。
希望這可以幫助其他人面臨同樣的問題。