我有一个用于查找的表,它将人类可读的值存储在一列中,同一文本在另一列中删除特殊字符和空格。例如,儿童节目"儿童节目"将出现在查阅列中作为" childrens-shows"。
不幸的是,相应的主表并不那么简单 - 由于历史原因,我没有创建自己,现在很难撤消,查找值实际上存储有周围的星号,例如: ' *儿童-节目*&#39 ;.
因此,在尝试将查找表sans-asterisks与带有星号的主表连接时,我认为CONCAT可以帮助我即时添加它们,例如。
SELECT *
FROM main_table m
INNER JOIN lookup_table l
ON l.value = CONCAT('*',m.value,'*')
......然后桌子就吐了。不确定我是否创建了无限循环或者确实搞砸了数据,但它需要ISP备份才能让表再次响应。我怀疑它是因为' *'符号可能是保留的,就像一个通配符,我已经要求数据库做相当于舔自己的肘部。无论哪种方式,我都犹豫不决,试验'鉴于它设法杀死数据库的壮观方式,找到答案。
提前感谢任何能够(a)告诉我上述内容对数据库做了什么,以及(b)我应该如何实际加入表格的人?
答案 0 :(得分:2)
使用CONCAT时,mysql不会使用索引。使用EXPLAIN来检查这一点,但我最近遇到的一个问题是,在大型表上,索引列就在那里,但是没有使用密钥。这不应该淹没整个桌子,只是让它变慢。可能是内存耗尽,开始交换然后中途崩溃,但你需要检查日志才能找到答案。
然而,根本原因显然是糟糕的桌面设计,这就是解决方案的所在。你得到的任何答案都可以让你解决这个问题只能是暂时的。
最佳解决方案是将此数据移至单独的表中。 “儿童节目”听起来像一个类别,因此在许多行中重复数据。这应该是'categories'表的id,这会阻止DB必须在表中的每一行上运行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'
我知道根据您在问题中提供的信息,这不是您可以做的事情,但实际上无法对标准化程度较低的数据库进行此类更改的原因比此处的代码更重要。如果没有资源或政治支持以正确的方式做事,你最终会遇到更多令人头痛的问题,从长远来看,最终会花费更多。和老板说句话的时间可能是:)