代码之家  ›  专栏  ›  技术社区  ›  ant

对MySQL文本类型列的查找

  •  16
  • ant  · 技术社区  · 7 年前

    我的桌子/模型有 TEXT 类型列,当筛选模型本身的记录时,AR where 生成正确的SQL并返回正确的结果,我的意思是:

    MyNamespace::MyValue.where(value: 'Good Quality')
    

    生成此SQL:

    SELECT `my_namespace_my_values`.* 
    FROM `my_namespace_my_values` 
    WHERE `my_namespace_my_values`.`value` = '\\\"Good Quality\\\"'
    

    再举一个我加入的例子 MyNamespace::MyValue 和过滤相同 value 列,但来自另一个模型(在模型上与 my_values )看看这个( 查询2 ):

    OtherModel.joins(:my_values).where(my_values: { value: 'Good Quality' })
    

    这不会产生正确的查询,这将在 价值 列,就好像它是一个字符串列而不是文本,因此会产生这样不正确的结果(只粘贴相关的位置):

    WHERE my_namespace_my_values`.`value` = 'Good Quality'
    

    现在我可以像在我的AR里一样通过这个 哪里 ,这将产生正确的结果,但查询略有不同。这就是我的意思:

    OtherModel.joins(:my_values).where('my_values.value LIKE ?, '%Good Quality%')
    

    最后我的问题终于来了。 这是什么?它是如何为模型上的位置(对于文本列类型)生成的?

    WHERE `my_namespace_my_values`.`value` = '\\\"Good Quality\\\"'
    

    也许是最重要的问题 在使用性能方面有什么不同 :

    其中'my\u namespace\u my\u values`.'value`='\\“高质量\\”
    

    还有这个:

    (my_namespace_my_values.value LIKE '%Good Quality%')
    

    更重要的是 如何使用join获取查询(查询2)生成这样的位置 :

    其中'my\u namespace\u my\u values`.'value`='\\“高质量\\”
    
    4 回复  |  直到 7 年前
        1
  •  5
  •   Rick James diyism    7 年前

    (部分答案——从MySQL端接近。)

    什么会/不会匹配

    案例1:(我不知道多余的反斜杠和引号是从哪里来的。)

    WHERE `my_namespace_my_values`.`value` = '\\\"Good Quality\\\"'
    
    \"Good Quality\"               -- matches
    Good Quality                   -- does not match
    The product has Good Quality.  -- does not match
    

    案例2:(查找 Good Quality 在任何地方 value )

    WHERE my_namespace_my_values.value LIKE '%Good Quality%'
    
    \"Good Quality\"               -- matches
    Good Quality                   -- matches
    The product has Good Quality.  -- matches
    

    案例3:

    WHERE `my_namespace_my_values`.`value` = 'Good Quality'
    
    \"Good Quality\"               -- does not match
    Good Quality                   -- matches
    The product has Good Quality.  -- does not match
    

    性能:

    • 如果 价值 已声明 TEXT 所有情况都很慢。
    • 如果 价值 没有索引,一切都很慢。
    • 如果 价值 VARCHAR(255) (或更小) 索引,案例1和3更快。它可以快速找到一行,而不是检查所有行。

    措辞不同:

    • LIKE 用一个 主要的 通配符( % )很慢。
    • 索引列对性能很重要,但是 文本 无法索引。
        2
  •  2
  •   Truth    7 年前

    这是什么?它是如何为模型上的位置(用于 文本列类型)?

    这是在活动记录(AREL)词汇引擎后面生成的。 请看下面我关于你第二个问题的答案,为什么。

    在性能方面,使用……

    “=”按整个字符串/块比较匹配 而like则按字符(按字符)匹配。

    在我的项目中,我得到了具有数百万行的表,根据我的经验,使用comparator“=”或regexp比在查询中使用like要快得多。

    如何使用joins获取查询(查询2)生成这样的位置…

    你能试试这个吗?

    OtherModel.joins(:my_values).where(OtherModel[:value].eq('\\\"Good Quality\\\"'))
    
        3
  •  2
  •   vipin    7 年前

    我认为这可能会有帮助。

    若要搜索\n,请将其指定为\n。若要搜索\,请将其指定为 \\这是因为反斜杠被解析器剥离一次 同样,当模式匹配时,只留下一个反斜杠 与…相匹配。

    link

    like和=是不同的运算符。

    =是对数字和字符串进行操作的比较运算符。比较字符串时,比较运算符比较整个字符串。

    类似的是一个字符串运算符,它逐字符比较字符。

    mysql> SELECT 'ä' LIKE 'ae' COLLATE latin1_german2_ci;
    +-----------------------------------------+
    | 'ä' LIKE 'ae' COLLATE latin1_german2_ci |
    +-----------------------------------------+
    |                                       0 |
    +-----------------------------------------+
    mysql> SELECT 'ä' = 'ae' COLLATE latin1_german2_ci;
    +--------------------------------------+
    | 'ä' = 'ae' COLLATE latin1_german2_ci |
    +--------------------------------------+
    |                                    1 |
    +--------------------------------------+
    
        4
  •  2
  •   Stephan Wiehr    7 年前

    “=”op正在查找精确匹配,而like op的工作方式更类似于模式匹配,其中“%”与正则表达式中的“*”类似。

    因此,如果您的条目

    1. 质量好
    2. 质量更高

    只有like才能得到两个结果。

    关于转义字符串,我不确定它是在哪里生成的,但看起来像是一些标准化转义,以获得对SQL有效的转义。