使用Memcache缓存MySQL结果,并对缓存结果进行排序/过滤


Caching MySQL results with Memcache and sorting/filtering cached results

为了帮助大家理解我的问题,我提出了一个场景:

我有用户A在我的web应用程序。

有一个特定的页面,其中有一个表,其中包含该用户的唯一信息。假设它是一个只显示用户a的客户列表,因为用户a和这些客户都在区域5。

其他用户被分配到不同的区域,看到不同的客户列表。

我想做的是缓存每个用户列表的所有结果。这不是问题,因为我可以使用:

    $MC = new Memcache;
    $MC->addserver('localhost');
    $data = $MC->get('customers');
    if($data)
    {
    } else {
        $data = $this->model->customersGrid($take, $skip, $page, $pageSize, $sortColumn, $sortDirection, $filterSQL, $PDOFilterParams);
        $MC->set('customers', $data);
    }
    header('Content-Type: application/json');
    return $data;

现在的挑战是以某种方式将来自我的用户表的SQL过滤器语法转换为一个可以过滤和排序数组的函数($data是一个JSON字符串,如果正确的话,我会将其转换为数组)。

仅供参考,下面是我在语句中构建WHERE子句时使用的别名数组:

    $KF = new KendoFilter;
    $KF->columnAliases = array(
        'theName' => 'name',
        'dimensions' => 'COALESCE((SELECT CONCAT_WS(" x ", height, width, CONCAT(length, unit)) FROM products_dimensions,
         system_prefs, units_measurement
         WHERE products_dimensions.productId = product.id
         AND units_measurement.id = system_prefs.defaultMeasurementId), "-")',
        'gridSearch' => array('theName', 'basePrice')
    );
    $filterSQL = $KF->buildFilter();

我的问题是什么是一个很好的方法来过滤和排序memcache数据,如果它是一个SQL查询?或者memcache已经内置了什么?

Memcache不能做到这一点-你不能用Memcache代替你的数据库(这不是它的目的),你只能存储键=>值对。

我认为更好的方法是将每个用户的每个数据存储在特定的内存缓存键中。

例如,如果用户A访问$user_id = 123的页面:

$data = $MC->get('customers_for_'.$user_id);

这样你只能得到用户123的客户。

一种更通用的方法是用它的参数为每个sql查询生成一个散列(但在大多数情况下,这可能是多余的)。例如,如果您有一个带有变量$a$b的查询select ... from ... where a = @a and b = @b,您可以执行以下操作(当然,您必须适应剑道,但要了解这个想法):

$query = "select ... from ... where a = @a and b = @b";
# crc32 because it is fast and the mem key does not get too long
$sql_crc = crc32($query.$a.$b);
$data = $MC->get("customers_".$sql_crc);

为了排除不同用户的哈希冲突(不太可能),您也可以在键中混合使用用户id:

$data = $MC->get("customers_for_".$user_id."_".$sql_crc);

BUT:如果你开始在你的应用程序中这样做,否则它太慢了,那么问题可能在于你的数据库(缺失/错误的索引,坏的列定义,复杂的关系等),时间应该更好地投资于修复数据库,而不是像这样解决问题。