He intentado utilizar primero en amplitud algoritmo para recuperar todo el conjunto de conexiones a la que el usuario seleccionado pertenece la siguiente manera:el análisis de grandes gráficos - Recuperando Clusters y cálculo de trayectorias más intensas
CREATE PROCEDURE Breadth_First (@StartNode varchar(50), @LinkStrength decimal(10,7) = 0.1, @EndNode varchar(50) = NULL)
AS
BEGIN
-- Automatically rollback the transaction if something goes wrong.
SET XACT_ABORT ON
BEGIN TRAN
-- Increase performance and do not intefere with the results.
SET NOCOUNT ON;
-- Create a temporary table for storing the discovered nodes as the algorithm runs
CREATE TABLE #Discovered
(
DiscoveredUser varchar(50) NOT NULL, -- The Node Id
Predecessor varchar(50) NULL, -- The node we came from to get to this node.
LinkStrength decimal(10,7) NULL, -- positive - from predecessor to DiscoveredUser, negative - from DiscoveredUser to predecessor
OrderDiscovered int -- The order in which the nodes were discovered.
)
-- Initially, only the start node is discovered.
INSERT INTO #Discovered (DiscoveredUser, Predecessor, LinkStrength, OrderDiscovered)
VALUES (@StartNode, NULL, NULL, 0)
-- Add all nodes that we can get to from the current set of nodes,
-- that are not already discovered. Run until no more nodes are discovered.
WHILE @@ROWCOUNT > 0
BEGIN
-- If we have found the node we were looking for, abort now.
IF @EndNode IS NOT NULL
IF EXISTS (SELECT TOP 1 1 FROM #Discovered WHERE DiscoveredUser = @EndNode)
BREAK
-- We need to group by ToNode and select one FromNode since multiple
-- edges could lead us to new same node, and we only want to insert it once.
INSERT INTO #Discovered (DiscoveredUser, Predecessor, LinkStrength, OrderDiscovered)
(SELECT mc.called_party, mc.calling_party, mc.link_strength, d.OrderDiscovered + 1
FROM #Discovered d JOIN monthly_connections mc ON d. DiscoveredUser = mc.calling_party
WHERE mc.called_party NOT IN (SELECT DiscoveredUser From #Discovered) AND mc.link_strength > @LinkStrength
UNION
SELECT mc.calling_party, mc.called_party, mc.link_strength * (-1), d.OrderDiscovered + 1
FROM #Discovered d JOIN monthly_connections mc ON d. DiscoveredUser = mc.called_party
WHERE mc.calling_party NOT IN (SELECT DiscoveredUser FROM #Discovered) AND mc.link_strength > @LinkStrength
)
END;
-- Select the results. We use a recursive common table expression to
-- get the full path from the start node to the current node.
WITH BacktraceCTE(Predecessor, DiscoveredUser, LinkStrength, OrderDiscovered, Path)
AS
(
-- Anchor/base member of the recursion, this selects the start node.
SELECT d.Predecessor, n. DiscoveredUser, d.LinkStrength, d.OrderDiscovered,
CAST(n. DiscoveredUser AS varchar(MAX))
FROM #Discovered d JOIN users n ON d. DiscoveredUser = n. DiscoveredUser
WHERE d. DiscoveredUser = @StartNode
UNION ALL
-- Recursive member, select all the nodes which have the previous
-- one as their predecessor. Concat the paths together.
SELECT d.Predecessor, n. DiscoveredUser, d.LinkStrength, d.OrderDiscovered,
CAST(cte.Path + ',' + CAST(n. DiscoveredUser as varchar(30)) as varchar(MAX))
FROM #Discovered d JOIN BacktraceCTE cte ON d.Predecessor = cte. DiscoveredUser
JOIN users n ON d. DiscoveredUser = n. DiscoveredUser
)
SELECT Predecessor, DiscoveredUser, LinkStrength, OrderDiscovered, Path FROM BacktraceCTE
WHERE DiscoveredUser = @EndNode OR @EndNode IS NULL -- This kind of where clause can potentially produce
ORDER BY OrderDiscovered -- a bad execution plan, but I use it for simplicity here.
DROP TABLE #Discovered
COMMIT TRAN
RETURN 0
END
El Gráfico (red social) que actualmente estoy analizando tiene 28 millones de conexiones y sin ignorar las conexiones débiles (establecer umbral con @LinkStrength) la ejecución está funcionando por mucho tiempo (hasta ahora no he obtenido ningún resultado y trataré de dejarlo funcionando durante la noche).
De todos modos, el siguiente paso es calcular los enlaces más cortos (más fuertes) entre dos usuarios (hay alrededor de 3 millones de usuarios). Estaba pensando en utilizar el algoritmo Djikstra, pero no estoy seguro de si es posible analizar dicha red en la PC que estoy usando actualmente (CPU cuádruple a 2,66 GHz, 4 GB de RAM) y los datos se almacenan en la base de datos MS SQL Server 2008.
Para resumir lo agradecería obtener algunas respuestas/sugerencias para las siguientes preguntas:
- ¿Es posible la ejecución de los consultas tan complejo como una encima de gráfico que describe (conexiones 28M, 3M usuarios) en la máquina descrita (2,66 GHz, 4 GB de RAM)?
- Si no es posible hay ningún otros posibles enfoques mediante los cuales el tiempo de ejecución podría reducirse (por ejemplo, la creación de tablas con resultados parciales)?
- ¿Recomendaría algún otro algoritmo para detectar clústeres y calcularía las rutas más cortas para el gráfico descrito?
¡Gracias!
Si usted puede pensar en algunas buenas heurísticas por la que adivinar en qué enlaces son más propensos que otros a continuación, es posible que desee probar un * ... – fmark
Usted es casi seguro de E/S de la CPU o el límite de memoria, agregar ejes y distribuir sus archivos de datos y temperatura mejorará el rendimiento de SQL. Incluso con las optimizaciones, fundamentalmente está realizando una tarea que SQL considera difícil de optimizar y, sin duda, seguirá golpeando los cuellos de botella de E/S a medida que su conjunto de datos crezca. La mayoría de las personas sensibles al tiempo intentan reducir mapas en este momento. – stephbu