【发布时间】:2015-04-19 06:54:22
【问题描述】:
我正在对单个表运行查询。我需要最终结果是一个行数组,其中当前用户被列为数据库行记录的消息中的参与者。两个参与者列是 staff 和 clients,并且包含用户 ID 和/或角色名称的序列化数组(例如,a:3:{i:0;s:8:"staffman";i:1;s:3:"203";i:2;s:3:"170";})。
在 SQL 查询中尝试过滤掉当前用户的所有不匹配项,或者执行一个全面查询(可能在数百行上),然后循环遍历它们以过滤掉用户不是参与者的那些?
SQL 选项:
$query = "SELECT * FROM ".self::$messages;
if($is_client) $query .= " WHERE type = 'clients'";
elseif($is_staff) $query .= " WHERE type = 'staff' AND (staff LIKE '%\"".$user->ID."\"%' OR staff LIKE 'staff\"%')";
elseif(!$is_admin)
{
$query .= " WHERE type = 'staff' AND (staff LIKE '%\"".$user->ID."\"%' OR staff LIKE 'staff\"%' OR staff LIKE 'clientman%'";
if($is_staffman) $query .= " OR staff LIKE 'staffman%'";
if($is_accountant) $query .= " OR staff like 'accountant%'";
$query .= ")";
}
$query .= " ORDER BY updated DESC";
循环选项:
$col = $is_client ? 'clients' : 'staff';
$query = "SELECT * FROM ".self::$messages." WHERE type = {$col} ORDER BY updated DESC";
// do the query, then check if there are results. if results...
foreach($results as $msg)
{
if(empty($msg->$col)) continue;
$users = unserialize($msg->$col);
if($is_client)
{
if(!in_array($user->ID, $users) && !in_array('client', $users)) continue;
}
elseif(!$is_admin && $msg->created_by != $user->ID)
{
if(!in_array($user->ID, $users))
{
if(!in_array('staff', $users))
{
if(!$is_clientman || !in_array('clientman', $users))
{
if(!$is_staffman || !in_array('staffman', $users))
{
if(!$is_accountant || !in_array('accountant', $users)) continue;
}
}
}
}
}
// match found, do stuff with it here
}
【问题讨论】:
-
很难预测像这样的复杂操作的性能。尝试两种方式并对其进行基准测试。
-
对您的备选方案进行基准测试。数据库可以快速处理这样的事情,而 php 非常慢,所以只需猜测一下,查询选项很可能是更快的选项。但是基准测试总是一件好事。
-
Sql 仍然会更快,即使它正在执行扫描。但是,如果您能够将 JSON 对象规范化为与列的关系,那么如果您避免
LIKE比较,性能将会大大提高。如果您继续存储 JSON,您可能会查看 MongoDB 以获取此数据——它将能够索引有效负载。 -
Stuart,因此标准化将涉及,您建议,在不同的表中为参与者(员工、客户)数组的每个元素创建一行,引用每一行中的消息 ID,一个每个用户的行?这就是你在说的吗?所以这会比在单行上做 LIKE 更快,对吧?
-
测试时哪个更快?
标签: php mysql sql loops wildcard