有效查询MSSQL数据库

时间:2014-06-28 20:57:33

标签: sql sql-server

我被赋予了从MSSQL数据库获取一些数据的任务。我不是数据库所有者,我没有能力进行任何更改或添加任何索引或任何东西。我必须与我所拥有的一起工作。 (我认为数据库设计师是吸毒者。)

通过python脚本访问数据库,但我会在这里显示伪代码,因为它是重要的SQL。

为此,有5项数据,我们称之为A,B,C,D和RecipeInstance。在数据库中,A,B,C和D被连接并作为A @ B @ C @ D存储在单个列中。 'A @ B @ C @ D'和RecipeInstance之间存在一对多的关系。

我的2个任务是:

1)鉴于A,B,C和D得到所有食谱

这在概念上很容易,但我的查询非常慢。这是我对此的疑问:

SELECT PDEName as recipe
FROM RecipeInstance
WHERE PdeInstanceId
IN (SELECT DISTINCT PdeInstanceId FROM RecipeTableValue WHERE CellValue
IN (SELECT DISTINCT PDEName FROM RunInstance WHERE PdeInstanceId
IN (SELECT PdeInstanceId FROM RunTableValue WHERE CellValue = 'A@B@C@D')))

此查询需要16秒。我真的需要让它更快。我尝试将其分解为4个单独的查询,但他们一起还需要16秒。这些表上没有有用的索引,我也无法创建任何索引。任何人都可以想到让这更快吗?

2)给定A,B,C和配方得到D

这更复杂,因为从RecipeInstance到TargetInstance之间没有任何关系,其中D是。以下是我提出的建议:

select PdeName as TargetPdeName
FROM TargetInstance
WHERE PdeName like 'A@B@C@%'

# this query returns between 20,000 and 40,000 rows

foreach TargetPdeName returned from the above query
    SELECT PDEName as RecipePdeName
    FROM RecipeInstance
    WHERE PdeInstanceId
    IN (SELECT DISTINCT PdeInstanceId FROM RecipeTableValue WHERE CellValue
    IN (SELECT DISTINCT PDEName FROM RunInstance WHERE PdeInstanceId
    IN (SELECT PdeInstanceId FROM RunTableValue WHERE CellValue = TargetPdeName)))

    if RecipePdeName == Recipe:
        # this is the one we want
        (a, b, c, d) = TargetPdeName.split('@')
        return d

所以这里的问题显然是我必须运行数万个查询,每个查询需要16秒。任何人都可以看到我如何以有效的方式向后追溯这种关系吗?

1 个答案:

答案 0 :(得分:1)

以下是JOINEXISTS次查询。试试两者,让我们知道它们是如何运行的。

1)

加入版本

SELECT DISTINCT reci.PDEName as recipe
FROM RecipeInstance reci
JOIN RecipeTableValue rectv ON reci.PdeInstanceId = rectv.PdeInstanceId
JOIN RunInstance runi ON rectv.CellValue = runi.PDEName
JOIN RunTableValue runtv ON runi.PdeInstanceId = runtv.PdeInstanceId 
WHERE runtv.CellValue = 'A@B@C@D'

EXISTS版本

SELECT PDEName as recipe
FROM RecipeInstance reci
WHERE EXISTS (
    SELECT * FROM RecipeTableValue rectv 
    WHERE rectv.PdeInstanceId = reci.PdeInstanceId
    AND EXISTS (
        SELECT * FROM RunInstance runi 
        WHERE runi.PDEName = rectv.CellValue
        AND EXISTS (
            SELECT * FROM RunTableValue runtv 
            WHERE runi.PdeInstanceId = runtv.PdeInstanceId
            AND CellValue = 'A@B@C@D'            
        )
    )
)

2)编辑:将ti.PdeName拆分为@并提取您需要定义自己的函数的最后一个值。见How do I split a string so I can access item x

加入版本

SELECT DISTINCT ti.PdeName
FROM RecipeInstance reci
JOIN RecipeTableValue rectv ON reci.PdeInstanceId = rectv.PdeInstanceId
JOIN RunInstance runi ON rectv.CellValue = runi.PDEName
JOIN RunTableValue runtv ON runi.PdeInstanceId = runtv.PdeInstanceId 
JOIN TargetInstance ti ON runtv.CellValue = ti.PdeName
WHERE reci.PDEName = "MyRecipe"

EXISTS版本

SELECT ti.PdeName
FROM TargetInstance ti
WHERE EXISTS (
    SELECT * FROM RunTableValue runtv
    WHERE runtv.CellValue = ti.PdeName
    AND EXISTS (
        SELECT * FROM RunInstance runi
        WHERE runi.PdeInstanceId = runtv.PdeInstanceId 
        AND EXISTS (
            SELECT * FROM RecipeTableValue rectv
            WHERE rectv.CellValue = runi.PDEName
            AND EXISTS (
                SELECT * FROM RecipeInstance reci
                WHERE reci.PdeInstanceId = rectv.PdeInstanceId
                AND reci.PDEName = "MyRecipe"
            )
        )
    )
)
相关问题