PDO绑定具有显着的性能影响

时间:2017-11-10 17:01:09

标签: php sql performance pdo sql-server-2012

我有一个特殊的查询,由于某种原因,在使用PDO绑定时(通过this)似乎有可怕的性能。我似乎对其他查询没有这个问题,所以我不确定它是否通常 这个查询,或者是否存在更大的基础PDO绑定的问题。

基本上,当我在没有绑定的情况下运行语句时(通过手动将原始绑定自身注入查询字符串[我明白这是不安全的并且可能导致SQL注入暴露]),语句运行大约100ms到200ms,对我们的申请是合理的。大多数查询通常具有绑定的速度,但无论出于何种原因,这个都没有。

当我通过框架自然地运行语句时,绑定将传递给PDO实例。以这种方式运行查询会导致它花费40,000毫秒(40秒),方式高于预期。

我已经尝试了我能想到的每一个组合来找到问题的根本原因,并且我确定它是PDO绑定。我甚至在没有PDO的情况下尝试了相同的查询,我也没有遇到同样的问题。在RDS中运行原始查询只需要80ms(由于开销较少,速度更快)。

我们还将PHP,Apache和我们的MSSQL / ODBC驱动程序更新到最新版本,但这些版本并没有改变性能。

我不知道为什么PDO绑定这么慢,而且我不知道我们对这种明显缓慢的曝光是什么(因为这个问题导致其他查询在我们的应用程序中可能会很慢)。我知道这个查询是我们现在唯一已知的问题实例。

查询本身:

$statement->execute($bindings)

绑定(替换查询中的?):

SELECT 
    top 10 [cars].[id], 
    [cars].[sponsor_id] 
FROM [cars] 
    INNER JOIN [drivers_cars]
        ON [cars].[id] = [drivers_cars].[car_id] 
            AND [drivers_cars].[driver_type_id] = ? -- 1
    INNER JOIN [drivers]
        ON [drivers_cars].[driver_id] = [drivers].[id] 
            AND [drivers].[deleted_at] IS NULL 
WHERE [cars].[deleted_at] IS NULL 
    AND (
        (
            SELECT COUNT(*) 
            FROM [drivers] 
                INNER JOIN [drivers_cars]
                    ON [drivers].[id] = [drivers_cars].[driver_id] 
            WHERE [drivers_cars].[car_id] = [cars].[id] 
            AND (
                (
                    SELECT COUNT(*) 
                    FROM [drivers_sponsors] 
                    WHERE [drivers_sponsors].[driver_id] = [drivers].[id] 
                        AND [drivers_sponsors].[driver_client_id] LIKE '469%'
                ) >= ? -- 1
                OR [drivers].[student_id] LIKE ? -- '469%'
                OR (
                    SELECT COUNT(*) 
                    FROM [drivers_contacts] 
                    WHERE [drivers_contacts].[driver_id] = [drivers].[id] 
                        AND [contact_type] IN (?, ?, ?, ?, ?, ?) -- (1, 2, 3, 4, 5, 6)
                        AND [phone_number] LIKE ? -- '469%'
                        AND [drivers_contacts].[deleted_at] IS NULL
                ) >= 1
            ) 
            AND [drivers].[deleted_at] IS NULL 
            AND [drivers_cars].[deleted_at] IS NULL
        ) >= 1 
        OR [cars].[sponsor_car_id] LIKE ? -- '469%'
    ) 
ORDER BY [drivers].[last_name] ASC

PDO实例:

"bindings" => [
    0 => 1,
    1 => 1,
    2 => "469%",
    3 => 1,
    4 => 2,
    5 => 3,
    6 => 4,
    7 => 5,
    8 => 6,
    9 => "469%",
    10 => "469%",
]

任何反馈都将不胜感激。

0 个答案:

没有答案