1

现在我是一名非常高级的 PHP 开发人员,并且对小型 MySQL 集有丰富的知识,但是我现在正在为我最近加入的一家初创公司构建一个大型基础架构,他们的服务器每天使用他们的服务器推送大约 100 万行数据强大的服务器能力和以前的架构。

我需要知道在数据库大小为 394.4 GB 的大型数据集(目前位于 8490 万行)中搜索的最佳方法是什么。它使用 Amazon RDS 托管,因此它没有任何停机时间或运行缓慢,只是我想知道在内部访问大型数据集的最佳方式是什么。

例如,如果我想搜索一个有 8400 万行的数据库,我需要 6 分钟。现在,如果我直接请求特定的 ID 或标题,它会立即为它服务。那么我将如何搜索大型数据集。

提醒您,通过传入一个变量通过数据库查找信息很快,但在搜索时执行速度非常慢。

MySQL查询示例:

SELECT u.*, COUNT(*) AS user_count, f.* FROM users u LEFT JOIN friends f ON u.user_id=(f.friend_from||f.friend_to) WHERE u.user_name LIKE ('%james%smith%') GROUP BY u.signed_up LIMIT 0, 100

84m 行下的查询非常慢。特别是 47.41 秒独立执行此查询,有什么想法吗?

我所需要的只是对挑战进行排序,然后我就可以随波逐流了。另外,我知道 MySQL 对于大型数据集以及 Oracle 或 MSSQL 之类的东西不是很好,但是我被告知现在要在 MySQL 而不是其他数据库解决方案上重建它。

4

2 回答 2

3

LIKE由于各种原因非常慢:

  • 除非您的LIKE表达式以常量开头,否则不会使用索引

    例如LIKE ('james%smith%'),好的,LIKE ('%james%smith%')不利于索引。您的示例不会在“ user_name”字段上使用任何索引。

  • 与常规运算符相比,字符串匹配是复杂的(算法上)业务。

解决:

  • 确保您的LIKE表达式以常量而不是通配符开头,如果您在该字段上有一个您可以使用的索引。

  • 如果您搜索整个单词,请考虑制作索引表(在“索引”一词的文献/图书馆上下文中,而不是数据库索引上下文中)。或者如果搜索随机经常重复的子字符串,则使用子字符串查找表。

    例如,如果所有用户名的形式为“FN LN”或“LN,FN” - 将它们拆分并将名字和/或姓氏存储在字典表中,在查询中加入该表(并进行直接相等) .

于 2010-08-02T00:58:45.890 回答
1
LIKE ('%james%smith%')

避免像瘟疫这样的事情。一般 DBMS 无法优化它们。

正确的方法是在插入或更新数据时计算这样的东西(名字和姓氏),以便在所有读取中分摊成本。这可以通过添加两个新列(索引)并使用插入/更新触发器来完成。

或者,如果您想要列中的所有单词,让触发器将数据分解为单词,然后使用应用程序级索引表来查找相关记录,例如:

main_table:
    id integer primary key
    blah blah blah
    text varchar(60)
appl_index:
    id index
    word varchar(20)
    primary key (id,word)
    index (word)

然后你可以查询appl_index找到那些同时包含和的ids,比 abominable 快得多。您也可以将实际单词拆分为单独的表格并使用单词 ID,但这只是个人喜好问题 - 它对性能的影响值得怀疑。jamessmithlike '%...'

您可能会遇到类似的问题,f.friend_from||f.friend_to但我以前从未见过这种语法(如果看起来是这样,上下文u.user_id可以是其中一个)。

基本上,如果您希望您的数据库可以扩展,请不要在您的选择中做任何看起来像每行函数的事情。从使用大型机数据库的人那里得到它,其中 8400 万行大约是我们的配置表的大小:-)

而且,与所有优化问题一样,衡量,不要猜测!

于 2010-08-02T01:02:03.900 回答