【发布时间】:2015-05-23 04:15:17
【问题描述】:
我正在尝试设置在两个不同表上匹配数据的东西。结果将按第二个表上的某些数据为真排序。但是,并非第一个表中的每个人都在第二个表中。我的问题是双重的。 1) 速度。我当前的 MYSQL 查询需要 4 秒来处理每个表上的数千个结果。 2) 没有正确订购。我需要它来按谁在线排序结果,但仍然按字母顺序排列。就目前而言,它根据 chathelp 表根据每个人是否在线对每个人进行排序,然后用 users 表填充其余部分。
我有什么:
SELECT u.name, u.id, u.url, c.online
FROM users AS u
LEFT JOIN livechat AS c ON u.url = CONCAT('http://www.software.com/', c.chat_handle)
WHERE u.live_account = 'y'
ORDER BY c.online DESC, u.name ASC
LIMIT 0, 24
users
+-----------------------------------------------------------+--------------+
| id | name | url | live_account |
+-----------------------------------------------------------+--------------|
| 1 | Lisa Fuller | http://www.software.com/LisaHelpLady | y |
| 2 | Eric Reiner | | y |
| 3 | Tom Lansen | http://www.software.com/SaveUTom | y |
| 4 | Billy Bob | http://www.software.com/BillyBob | n |
+-----------------------------------------------------------+--------------+
chathelp
+------------------------------------+
| chat_id | chat_handle | online |
+------------------------------------+
| 12 | LisaHelpLady | 1 |
| 34 | BillyBob | 0 |
| 87 | SaveUTom | 0 |
+------------------------------------+
我希望收到的数据是什么样的:
+----------------------------------------------------------------------+
| name | id | url | online |
+----------------------------------------------------------------------+
| Lisa Fuller | 1 | http://www.software.com/LisaHelpLady | 1 |
| Eric Reiner | 4 | | 0 |
| Tom Lansen | 3 | http://www.software.com/SaveUTom | 0 |
+----------------------------------------------------------------------+
说明:Billy 因没有真实账户而立即被排除在外。 Lisa 比 Eric 更早,因为她在线。 Tom 在 Eric 之后是因为他离线并且在数据中按字母顺序排列。两个表之间唯一匹配的数据是 url 列与 chat_handle 列的一部分。
我得到的是什么:
(基本上,我得到的是 Lisa、Tom,然后是 Eric)
无论他们是否在线,我都会首先列出聊天帮助表中的每个人。所以先来 600 人,然后我从 users 表中得到不在两个表中的其余人。我需要按字母顺序将聊天帮助表中离线的人分类到用户表中。因此,如果 Lisa 和 Tom 是唯一的在线用户,他们将排在第一位,但用户表中的其他所有人,无论他们是否设置了聊天帮助句柄,都将按字母顺序排在这两个用户之后。
同样,我需要在 4 秒内对它们进行排序并弄清楚如何做到这一点。我在两个表上都尝试过索引,但它们没有帮助。解释说它正在使用表用户上的键(名称)点击行 4771 -> 使用 where;使用临时;使用 filesort 并在 table2 NULL 上使用 1054 行的键,而额外的列中没有任何内容。
任何帮助将不胜感激。
编辑以添加表格并解释语句
CREATE TABLE `chathelp` (
`chat_id` int(13) NOT NULL,
`chat_handle` varchar(100) NOT NULL,
`online` tinyint(1) NOT NULL DEFAULT '0',
UNIQUE KEY `chat_id` (`chat_id`),
KEY `chat_handle` (`chat_handle`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
CREATE TABLE `users` (
`id` int(8) NOT NULL AUTO_INCREMENT,
`name` varchar(50) NOT NULL,
`url` varchar(250) NOT NULL,
`live_account` varchar(1) NOT NULL DEFAULT 'n',
PRIMARY KEY (`id`),
KEY `livenames` (`live_account`,`name`)
) ENGINE=MyISAM AUTO_INCREMENT=9556 DEFAULT CHARSET=utf8
+----+-------------+------------+------+---------------+--------------+---------+-------+------+----------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+------------+------+---------------+--------------+---------+-------+------+----------------------------------------------+
| 1 | SIMPLE | users | ref | livenames | livenames | 11 | const | 4771 | Using where; Using temporary; Using filesort |
| 1 | SIMPLE | chathelp | ALL | NULL | NULL | NULL | NULL | 1144 | |
+----+-------------+------------+------+---------------+--------------+---------+-------+------+----------------------------------------------+
【问题讨论】:
-
您的查询速度很慢,因为 1) 处理程序上没有可以使用的索引,2) 由于 concat 或您有 blob 类型的列,您有一个磁盘排序。
-
因此,如果我要将 concat 字符串添加到 chathelp.chat_handle 中的信息中,我可以做一个相等的匹配来加速它吗?但是当显示句柄时,我必须从 MYSQL 中的数据中删除它。或者,使用完整的 URL 在 chathelp 上创建另一个列,以便我可以匹配它?希望避免改变任何东西。
-
好的。看起来我的星期五晚上被枪杀了。感谢您的帮助,我接受了我的问题 #2 的答案。
标签: mysql performance join left-join