Php 将MySQL值存储为整数

Php 将MySQL值存储为整数,php,mysql,sql,join,jointable,Php,Mysql,Sql,Join,Jointable,我有两个数据库表,用于创建Twitter风格的跟踪系统 sh_subscriptions => id => user_id => feed_id sh_feeds => id => item => shop_name => feed_id 在sh\u订阅中存储feed\u id而不是shop\u name的问题在于,它需要大量的表连接: $id = $_POST['id']; $user_id

我有两个数据库表,用于创建Twitter风格的跟踪系统

sh_subscriptions
    => id
    => user_id
    => feed_id

sh_feeds
    => id
    => item
    => shop_name
    => feed_id
sh\u订阅中存储
feed\u id
而不是
shop\u name
的问题在于,它需要大量的表连接:

$id = $_POST['id'];
$user_id = $id['id'];
$shop_name = mysqli_escape_string($con, $_POST['shop_name']);

$query = "SELECT * FROM sh_subscriptions s INNER JOIN sh_feeds f ON s.feed_id = f.feed_id WHERE s.user_id = $user_id AND f.shop_name = '$shop_name'";
$result = mysqli_query($con, $query) or die(mysqli_error($con));

if (mysqli_num_rows($result) > 0)
{
    $query2 = "DELETE FROM sh_subscriptions s INNER JOIN sh_feeds f ON s.feed_id = f.feed_id WHERE s.user_id = $user_id AND f.shop_name = '$shop_name'";
    $result2 = mysqli_query($con, $query2) or die(mysqli_error($con));
}

else
{
    // insert the row instead
}
(我知道if语句中的某个地方有错误,但稍后我会担心这一点。)

如果我将
feed\u id
替换为
shop\u name
,我将能够用以下内容替换第5行:

$query = "SELECT * FROM sh_subscriptions WHERE user_id = $user_id AND shop_name = '$shop_name'";

我的问题是:在可能的情况下,是否总是最好将MySQL值存储为整数,或者在这种情况下,让
sh_订阅
包含
shop_name
,而不是
feed_id

您的sh_订阅表实际上是一个将用户与提要关联的多对多联接表。这被认为是设计数据库模式的好方法

您的基本概念是:您有一个用户集合和一个提要集合。每个用户可以订阅零个或多个提要,并且每个提要可以有零个或多个订阅者

要输入订阅,请在sh_订阅表中创建一行。若要取消,请删除该行

你说有“很多桌子连接”。恕我直言,这不是很多桌子连接。MySQL是为这种连接而设计的,它将很好地工作

我对您的SHU订阅表有一些建议

  • 去掉
    id
    列。而是将user_id和feed_id列设置为复合主键。这样,您将自动防止重复订阅
  • 添加一个
    活动的
    列。。。一个短整数。。。坐到桌子上。将其设置为
    1
    时,您的订阅处于活动状态。这样,您可以通过将
    active
    设置为0来取消订阅
  • 如果您关心这一点,还可以添加一个
    subscribed\u date
  • 在表上创建两个复合非唯一索引
    (活动,用户id,提要id)
    (活动,提要id,用户id)
    。这将大大加快连接这样的表的查询
  • 查询片段:

       FROM sh_feed f
       JOIN sh_subscription s ON (f.feed_id = s.feed_id AND s.active = 1)
       JOIN sh_users u ON (s.user_id = u.user_id)
      WHERE f.shop_name = 'Joe the Plumber'
    

    如果你达到了数亿用户或提要,你可能需要考虑对这个表进行非正规化处理。也就是说,例如,重新定位店铺名称文本,使其位于sh_subscriptions表中。但现在不行

    编辑我建议多个复合覆盖索引。例如,如果您将提要加入到用户中,MySQL将通过确定sh_提要中与您的选择匹配的行来满足您的查询

    然后,它确定提要id,并随机访问提要id上的复合索引。然后,它需要查找该提要id的所有用户id值。它可以从随机访问索引的点扫描索引,而无需返回到表。这确实很快。这叫做覆盖指数

    另一个覆盖索引处理从已知用户开始并继续查找提要的查询。索引中列的顺序很重要:随机访问只能从索引的第一列(最左边)开始

    要理解的技巧是,这些索引既可以随机访问,也可以按顺序扫描


    另一个注意事项是,如果联接表中只有两列,则其中一个覆盖索引也是主键,另一个包含与主键顺序相反的列。您不需要任何重复的索引。

    如果店铺名称发生更改怎么办?@DanBracuk这是保留提要id的唯一原因吗?如果两个提要具有相同的店铺名称但项目不同怎么办?数据库中的每一行都应该由一个唯一的值标识。即使聚合表仅由两个外键组成,也希望另一列包含主键,即使外键的组合可以用作主键。您可以通过这种方式保持数据的可移植性,以便从应用程序的任何位置查询这些数据。此外,整数很容易验证。另一方面,字符串有点难,因为您需要准确地指定它们中需要的内容和不需要的内容。@func0der,您提到的设计原则(始终提供代理主键)在使用实体-关系样式的数据库设计时根本无效。如这里所述(),我不会删除
    sh_subscriptions
    @func0der中的
    id
    列,如果原始提问者采用我在这里建议的数据库设计的实体关系样式,那么他的连接表(也称为多对多关系表)根本不需要像id键那样的代理主键。该密钥混淆了数据完整性问题。它给表维护增加了不必要的开销,也会给查询增加开销。你是对的,有些主键总比没有主键好。但是(user_id,feed_id)是一个非常好的主键。非常感谢您的全面回复。几个问题:1)您是否建议使用
    active
    列替换添加和删除数据库字段?如果是这样,知道用户曾经订阅过提要,但现在没有订阅提要有什么好处(如果
    active
    等于0,情况就是这样)?2) 为什么需要两个复合的非唯一索引?
    active
    不能替代将行插入订阅表。但我确实建议用它来代替删除行。如果您确定不需要了解历史订阅,请继续并删除。这是一种设计偏好。