【问题标题】:Improving the SQL commands to display preceding and following values in alphabetical order改进 SQL 命令以按字母顺序显示前后值
【发布时间】:2017-01-24 15:48:15
【问题描述】:

通过以下两个 SQL 命令,我按字母顺序查找显示的词条之前的 15 个词条和词条之后的 15 个词条。

关键字列已编入索引。执行时间已注明。

是否有更快或更好的解决方案在大型字母列表中查找多个前后值?

SELECT * 
FROM  
    (SELECT 
         `keyword`, `num_keyword`,`stem`, `gram_1_word_group` 
     FROM 
         `ds_1_headword` 
     WHERE 
         `keyword` COLLATE `utf8_icelandic_ci` <= 'Patagónía' 
     ORDER BY 
         `keyword` COLLATE `utf8_icelandic_ci` DESC, `num_keyword` 
     LIMIT 15) AS `table`
ORDER BY 
    `keyword` COLLATE `utf8_icelandic_ci` ASC, `num_keyword

5.4222950935364

 SELECT `keyword`, `num_keyword`,`stem`, `gram_1_word_group` 
 FROM `ds_1_headword` 
 WHERE `keyword` COLLATE `utf8_icelandic_ci` > 'Patagónía'
 ORDER BY `keyword` COLLATE `utf8_icelandic_ci` ASC, `num_keyword` limit 15 

7.3961861133575

如果我没记错的话,当列与查询中的排序规则相同时,这是冗余信息,可以删除,希望也可以更快。

SELECT * 
FROM (SELECT `keyword`, `num_keyword`,`stem`, `gram_1_word_group` 
    FROM `ds_1_headword` 
    WHERE `keyword` <= 'Patagónía' 
    ORDER BY `keyword` desc, `num_keyword` limit 15) AS `table`
    ORDER by `keyword` ASC, `num_keyword

 SELECT `keyword`, `num_keyword`,`stem`, `gram_1_word_group` 
 FROM `ds_1_headword` 
 WHERE `keyword` > 'Patagónía'
 ORDER BY `keyword` ASC, `num_keyword` limit 15 

更新 1.查询说明

id  select_type     table   type    possible_keys   key     key_len     ref     rows    Extra   
1   PRIMARY     <derived2>  ALL     NULL    NULL    NULL    NULL    15  Using filesort
2   DERIVED     ds_1_headword   range   keyword     keyword     302     NULL    23205   Using where

2.查询的解释

id  select_type     table   type    possible_keys   key     key_len     ref     rows    Extra   
1   SIMPLE  ds_1_headword   range   keyword     keyword     302     NULL    30646   Using where; Using filesort

【问题讨论】:

  • 感谢您纠正问题。
  • 您可以发布示例数据和预期结果吗?您的查询目前只会获得 15 个词条“紧接在前面”和“紧接在”字符串“Patagonia”之后。一次需要 2 x 15 = 30 条记录吗?您想知道为什么需要 5 秒和 7 秒吗?
  • 没错,样本数据有问题 - 每次显示新词条时,我都会搜索 53000 条记录(也显示新的字母列表,其中包含 15 个前面和 15 个后面的词条)。是的,查询必须花费更少的时间。
  • 如果整个列表只有 53K 行,您应该让应用程序加载所有这些行并在应用程序的内存中执行此操作 - 它应该快如闪电。此外,如果需要 5 秒,您的数据库似乎对这种类型的查询根本没有很好地优化。如果可以的话,你应该修复数据库;否则,在应用程序中做一个大的SELECT 并以应用程序使用的任何语言管理 53000 的列表,而不是这个性能不佳的 mysql 查询。您是否有能力修复数据库或应用程序开发人员,或两者兼而有之?
  • 如果我的评论正在为您提供答案,请告诉我,我很乐意以这种方式发布:)

标签: mysql alphabetical


【解决方案1】:

如果您正在寻找速度,请将keyword 列声明为CHARACTER SET utf8 COLLATION utf8_icelandic_ci

通过在查询中声明不同的排序规则,不能使用索引,因此您正在扫描整个表。

对于获取给定单词(加上给定行)之前和之后的 15 行,这是最佳的:

( SELECT `keyword`, `num_keyword`,`stem`, `gram_1_word_group` 
       FROM ds_1_headword
       WHERE keyword <  'Patagónía'
       ORDER BY keyword DESC LIMIT 15 )
UNION ALL
( SELECT `keyword`, `num_keyword`,`stem`, `gram_1_word_group` 
       FROM ds_1_headword
       WHERE keyword >= 'Patagónía'
       ORDER BY keyword ASC  LIMIT 16 )
ORDER BY keyword;   -- assuming you want the result sorted

MariaDB 10.0.2 具有“窗口化功能,它可以在没有UNION 的情况下执行类似的操作,可能效率更高。

如果您需要通过各种排序规则对 same 列进行排序,那么您就不走运了。重新考虑架构(添加更多列?)和/或要求(不需要多个排序规则?)。

【讨论】:

  • 幸运的是,我使用了相同的排序规则。当系统允许我时,我会奖励这个答案。确实非常快 - 当列已经在此排序规则中时,将这两个命令组合为一个,而不是在查询中使用 utf8_icelandic_ci。查询时间为0.013284921646118!!!谢谢。
  • 更正:MariaDB 10.2.
【解决方案2】:

如果您想让数据检索更快,这里有几个广泛的主题应该会让您朝着正确的方向前进:

  1. 数据库是否在“足够强大”的机器上运行?对于一个 53K 行的表来说,即使是具有 1 个内核和 4GB RAM 的机器也将“足够强大”,除非该机器被其他工作负载淹没。

  2. 如果机器“足够强大”,那么您应该查看 mysql 表并检查 执行计划(如果需要,请查看)。您需要做的一件非常常见的事情是检查您正在搜索/排序的列上是否有一个 INDEX (在您的情况下为keyword)。 Here's a link on indexes in mysql

  3. 如果使数据库变得更快变得困难,您可以将 ALL 数据拉入 PHP,如果执行 PHP 的机器“足够强大”,脚本应该可以管理53K 值并在几毫秒而不是几秒内拉出“15 之前,15 之后”。至于如何在 PHP 中执行此操作,这里有一个 PHP Tutorial page for SELECTing from a table 的示例。

希望这能让您走上正确的道路。如果您仍然需要帮助,尽管问!

【讨论】:

  • 这个问题是由托管数据库服务器过载引起的 - 现在时间是 0.2039909362793。无论如何,我将继续检查您的建议,并将问题留到明天。将 53000 个结果存储在 php 中的哪个变量的子问题?
  • 好! 0.2 秒的时间更有意义。我仍然建议你把它放在应用程序内存中,只要大小不太大。如果它只是 53K 字的列表(或者如果您需要使用 53K 行中的多列),并且每行由 50 个字节的关键字和 50 个字节的其他内容组成,则只需要 53K x 100 = 5.3 MB,这对于具有 4GB 或更多内存的系统来说不是问题。 PHP“列表”对象甚至数组都可以让您保存单词列表,按字母顺序排序,并毫无问题地检索 15 个之前/之后的单词。
  • 如果这个答案对你有帮助,你能把它标记为答案吗?
  • 刷新新页面后数组变量为空。我不确定,如果我解释得很好。每次显示词条时,都会重新加载页面并显示新的单词列表。
  • 如果您在网页上显示此数据,我只能猜测,因为您没有指定,那么您知道每次“刷新”页面时,服务器都会必须重新执行您的 PHP 脚本并重新填充数组,和/或您必须使用 Javascript 在客户端浏览器中处理它。我认为您的问题已经发生了很大的变化,如果您需要更多帮助,您应该将其作为新问题发布。祝你好运! :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-01-24
  • 2011-09-23
  • 1970-01-01
  • 2019-12-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多