【问题标题】:How to scale efficiently geo restriction data from MySQL data storage如何从 MySQL 数据存储中有效地扩展地理限制数据
【发布时间】:2014-11-12 06:29:15
【问题描述】:

我有以下表格。

CREATE TABLE `media_scores` (
  `media_id` int(10) unsigned NOT NULL,
  `sorting_score` float unsigned NOT NULL DEFAULT '0',
  `date_added` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
  `date_updated` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`media_id`),
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

CREATE TABLE `media_restrict` (
  `media_id` int(11) NOT NULL,
  `restrict_type` enum('exclude','include') NOT NULL,
  `country_code` char(2) NOT NULL,
  PRIMARY KEY (`media_id`,`restrict_type`,`countryCode`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

表 media_scores 有 180 万条记录。 表 media_restrict 具有相同或更多的记录。

以下是里面的一些示例数据: media_scores

+----------+---------------+-------------+--------------+
| media_id | sorting_score | date_added  | date_updated |
+----------+---------------+-------------+--------------+
|        1 |           25  | 2014-11-05  | 0000-00-00   |
|       2  |           16  | 2014-11-05  | 0000-00-00   |
|       3  |           33  | 2014-11-05  | 0000-00-00   |
|       4  |           11  | 2014-11-04  | 0000-00-00   |
+----------+---------------+-------------+--------------+

媒体限制

+----------+---------------+--------------+
| media_id | restrict_type | country_code |
+----------+---------------+--------------+
|        1 | exclude       | US           |
|        1 | exclude       | UK           |
|        2 | include       | US           |
|        2 | include       | CA           |
|        3 | include       | CN           |
+----------+---------------+--------------+

我正在运行以下查询:

SELECT ms.*
FROM media_scores as ms
LEFT OUTER JOIN media_restrict AS mr
ON ms.media_id = mr.media_id and mr.restrict_type = 'exclude' and mr.country_code = 'CA'
LEFT OUTER JOIN media_restrict AS mr2
ON ms.media_id = mr2.media_id AND mr2.restrict_type = 'include' AND mr2.country_code = 'CA'
LEFT OUTER JOIN media_restrict AS mr3
ON ms.media_id = mr3.media_id AND mr3.restrict_type = 'include' AND mr3.country_code != 'CA'
WHERE mr.media_id IS NULL AND
(CASE mr2.media_id WHEN ms.media_id THEN NULL ELSE mr3.media_id END) IS NULL;

实现这一目标:

+----------+---------------+------------+--------------+
| media_id | sorting_score | date_added | date_updated |
+----------+---------------+------------+--------------+
|        1 |            25 | 2014-11-05 | 0000-00-00   |
|        2 |            16 | 2014-11-05 | 0000-00-00   |
|       4  |            11 | 2014-11-04 | 0000-00-00   |
+----------+---------------+------------+--------------+

在小子集上 - 查询运行良好。 在 1.8M 上,我遇到了可扩展性问题。

我最终想要实现的基本目标是将 media_scores 中的项目显示给仅允许的国家/地区。

我在基础架构方面非常灵活,因此 MySQL 可能不是解决方案,但它是我能想到的全部。

随着我填写更多数据和更多国家/地区限制,数据集将会增长。

如何在更大范围内有效地根据国家/地区限制我的数据。任何给定的服务如何检查内容限制(例如 Youtube 不能根据国家/地区显示内容)。

有两件事需要考虑:速度和准确性。 当前的基准大约是 13 秒,如果我将其作为数据集加载,然后我必须对其进行操作 - 它的时间太长了。准确性意味着我需要确保获得所需的正确结果。目前提到的查询是正确的。

注意:数据经常更新,但不是每分钟更新一次(我会说每小时左右可能更多) - 因此 Vertica 可以提供大数据集以进行高效查询,但由于 Vertica 不能很好地支持更新或删除 - 它排除了这一点。

【问题讨论】:

    标签: mysql database scalability


    【解决方案1】:

    您的问题有点模棱两可 - 对于任何给定的 media_id,您是否可以包括被排除的国家?似乎如果你包括国家,自然的假设是所有其他国家都被排除在外,反之亦然(如果你排除国家,所有其他国家都会被包括在内)——这是真的吗?如果是这样,那么对于给定的 media_id,您将只有 include 或 exclude,但不能同时拥有。

    如果我正确地解释了您的查询,那将通过让您不必担心这部分来简化它:

    LEFT OUTER JOIN media_restrict AS mr3
    ON ms.media_id = mr3.media_id AND mr3.restrict_type = 'include' AND mr3.country_code != 'CA'
    WHERE mr.media_id IS NULL AND
    (CASE mr2.media_id WHEN ms.media_id THEN NULL ELSE mr3.media_id END) IS NULL;
    

    您还可以做出其他重大改进,但取决于您对我上面问题的回答,所以我先让您回答。

    【讨论】:

    • 这是正确的 - 对于给定的 media_id,您只能被包含或排除,不能同时包含或排除。但是我需要“全局” media_id 的最后一部分。如果您查看预期结果:media_id 4 需要显示 - 既不包括也不排除,因为它不限于任何国家/地区。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-12-12
    • 2011-09-05
    • 1970-01-01
    • 2023-04-08
    • 1970-01-01
    • 1970-01-01
    • 2019-07-07
    相关资源
    最近更新 更多