这是这个复杂的MySQL多表查询的最佳方法吗?

时间:2013-05-16 00:05:06

标签: mysql regex

我正构建一个复杂的多表MySQL查询,即使它有效,我也想知道我可以让它更简单。

背后的想法是这样,使用记录所有网站交互的事件表,选择10个最受欢迎的博客帖子的ID,标题和Slug,并按大多数命中降序排序。

SELECT content.id, content.title, content.slug, COUNT(events.id) AS hits 
FROM content, events
WHERE events.created >= DATE_SUB(NOW(), INTERVAL 1 MONTH)
    AND events.page_url REGEXP  '^/posts/[0-9]'
    AND content.id = events.content_id
GROUP BY content.id
ORDER BY hits DESC
LIMIT 10

博客帖子网址具有以下格式:

/posts/2013-05-16-hello-world

正如我所提到的那样似乎有用,但我确信我可以做得更干净。

谢谢,

2 个答案:

答案 0 :(得分:1)

您可以使用left函数

代替正则表达式
SELECT content.id, content.title, content.slug, COUNT(events.id) AS hits FROM content JOIN events ON content.id = events.content_id
            WHERE events.created >= DATE_SUB(NOW(), INTERVAL 1 MONTH)
            AND left( events.page_url, 7) = '/posts/'
            GROUP BY content.id
            ORDER BY hits DESC
            LIMIT 10)

但是,这只是我的头脑,没有fiddle,未经测试。在评论中提出的JOIN建议也很好,并且反映在我的回答中。

答案 1 :(得分:1)

created上的条件和page_url上的条件都是范围条件。在SQL查询中,每个表只能获得一个范围条件的索引辅助,因此您必须选择一个或另一个来进行索引。

我会在事件表上通过两列(content_id,created)创建一个索引。

ALTER TABLE events ADD KEY (content_id, created);

我假设按创建日期限制比通过page_url限制更具选择性,因为我假设“/ posts /”将匹配大多数事件。

在按创建日期缩小匹配行之后,必须由SQL层处理page-url条件,但希望这不会太低效。

SQL-89(“逗号样式”)连接语法和SQL-92 JOIN语法之间没有性能差异。我建议使用SQL-92语法,因为它更清晰,并且它支持外连接,但 performance 不是使用它的理由。 SQL查询优化器支持两种连接样式。

临时表和文件排序通常代价高昂。此查询绑定创建临时表并使用filesort,因为您对不同的列使用GROUP BY和ORDER BY。您只能希望临时表足够小以适应tmp_table_size限制(或增加该值)。但是如果content.title或content.slug是BLOB / TEXT列,那将无助于临时表,无论如何都会强制在磁盘上假脱机临时表。