3

我有一个用于查找的表,它将人类可读的值存储在一个列中,并且在另一列中存储了相同的文本,其中删除了特殊字符和空格。例如,值“Children's Shows”将在查找列中显示为“childrens-shows”。

不幸的是,对应的主表并不是那么简单——由于历史原因,我没有自己创建,现在很难撤消,查找值实际上是用周围的星号存储的,例如'*childrens-shows*'。

因此,在尝试将无星号的查找表与具有星号的主表连接时,我认为 CONCAT 会帮助我即时添加它们,例如;

    SELECT * 
      FROM main_table m 
INNER JOIN lookup_table l 
        ON l.value = CONCAT('*',m.value,'*')

……然后桌子就烤好了。不确定我是创建了一个无限循环还是真的搞砸了数据,但它需要一个 ISP 备份才能让表再次响应。我怀疑这是因为“*”符号可能是保留的,就像通配符一样,我已经要求数据库做相当于舔自己的肘部的事情。无论哪种方式,鉴于它设法杀死数据库的壮观方式,我都不愿“实验”以找到答案。

提前感谢任何可以(a)告诉我上面对数据库实际做了什么,以及(b)我应该如何实际加入表格的人?

4

1 回答 1

2

使用 CONCAT 时,mysql 不会使用索引。使用 EXPLAIN 来检查这一点,但我最近遇到的一个问题是,在一张大表上,索引列在那里,但没有使用键。然而,这不应该让整个桌子感到厌烦,只是让它变慢。可能它内存不足,开始交换,然后中途崩溃,但您需要检查日志才能找到答案。

然而,根本原因显然是糟糕的表格设计,而这正是解决方案所在。您得到的任何可以解决此问题的答案最多只能是暂时的。

最佳解决方案是将这些数据移动到单独的表中。“儿童节目”听起来像是一个类别,因此在许多行中重复数据。这实际上应该是“类别”表的 id,这将防止数据库必须在表中的每一行上运行 CONCAT,因为您可以这样做:

    SELECT * 
      FROM main_table m 
INNER JOIN lookup_table l 
        ON l.value = m.value
   /* and optionally */
INNER JOIN categories cat
        ON l.value = cat.id
     WHERE cat.name = 'whatever'

我知道鉴于您在问题中提供的信息,您可能无法做到这一点,但实际上无法对严重规范化的数据库进行此类更改的原因比此处的代码更重要。如果没有资源或政治支持以正确的方式做事,你最终会遇到更多这样的麻烦,从长远来看,这最终会花费更多。也许是时候和老板谈谈了:)

于 2012-10-17T10:18:01.800 回答