2

我有一个可以被描述为需要优化的大型 MySQL 查询。查询所做的是选择与反向链接处理相关的数据。

反向链接处理是指将大约 100,000 个链接添加到数据库中。这些链接被分批选择和卷曲,以寻找指向我网站的反向链接。

我在此查询中选择的信息是:

  • complete- 处理完成(bool 1 或 0)
  • current_step- 我们在 3 中的哪一步(1、2 或 3)
  • percent- 我现在的步骤完成了多少百分比(0.0-100.0)
  • total_rows- 数据库中具有该表键 ID(整数)的所有行的完整计数
  • live_rows- 与我的页面的实时反向链接找到的链接数(整数)
  • dead_rows- 找到的没有反向链接的链接数(整数)

注意:当前步长是通过查看checked列的 MAX() 值来计算的。如果找不到链接,我们会检查两次链接。因此,当工具第一次开始运行时,所有checked值都设置为零(因为处理尚未开始),因此我们希望当前步骤为步骤 1。然后我们处理所有行并将所有checked值设置为 1,并且对于第 1 步,百分比将返回 100.00,然后程序开始对第一次发现已失效的链接进行双重检查。随着第二次检查的进行,一些行被设置为 2,因此 MAX(checked) 在第二步中返回 2。完成第二步后,程序将processing_complete列更改为 1,我们返回 3 作为完成的当前步骤。我们返回 3 是因为它会导致 UI 变为完成状态。

我有 2 张桌子,这是它们的一般结构。请注意,这tablekey_id是一个外键从google_sort_backlink_domains返回到中的idgoogle_sort_tablekey

google_sort_tablekey:

  • id- 主键、索引列
  • unique_id- 唯一哈希用作此工具运行的唯一标识符
  • processing_completed- 处理完成时布尔标志设置为 1

google_sort_backlink_domains:

  • id- 主键、索引列
  • tablekey_id- google_sort_tablekey 的外键
  • checked- 当链接卷曲时,布尔标志设置为 1,然后
  • link_found- 如果在第一次或第二次检查期间发现反向链接,则布尔标志设置为 1
  • link_href- 字符串,链接到页面

这是该数据可能看起来的一个非常小的示例

google_sort_tablekey:
id     unique_id       processing_completed
23     35799756448     1
24     78698778978     0

google_sort_backlink_domains:
id     tablekey_id     checked     link_found     link_href
11     23              1           0              http://www.website.com/1...
12     24              0           0              http://www.website.com/2...
13     23              1           1              http://www.website.com/3...
14     24              1           1              http://www.website.com/4...
15     24              1           1              http://www.website.com/5...
16     24              0           0              http://www.website.com/6...

这是我的查询,但是当我处理 100,000 行的数据集时,它需要很长时间。我添加了空格以帮助提高可读性,并且我还硬编码为 24 的 id,这将在生产中使用变量进行设置。

SELECT `processing_completed` AS complete,

ROUND((SELECT((SUM(IF((`link_found` = 1 OR `checked` >= (SELECT MAX(`checked`) 
    FROM `google_sort_backlink_domains` WHERE `tablekey_id` = 24)), 1, 0)) / SUM(1))*100) AS percent
FROM `google_sort_backlink_domains` WHERE `tablekey_id` = 24), 1) AS percent,

CASE WHEN `processing_completed` = 1 THEN 3 WHEN MAX(`checked`) = 0 THEN 1 ELSE MAX(`checked`) END AS current_step,

(SELECT COUNT(1) FROM `google_sort_backlinks` WHERE `tablekey_id` = 24) AS total_rows,

(SELECT COUNT(1) FROM `google_sort_backlink_domains` WHERE `tablekey_id` = 24) AS unique_domains,

(SELECT COUNT(1) FROM `google_sort_backlink_domains` WHERE `tablekey_id` = 24 AND `link_found` = 1) AS live_rows,

(SELECT COUNT(1) FROM `google_sort_backlink_domains` WHERE `tablekey_id` = 24 
AND `checked` >= (
SELECT CASE WHEN `processing_completed` = 1 THEN 3 WHEN MAX(`checked`) = 0 THEN 1 ELSE MAX(`checked`) END FROM `google_sort_backlink_domains` WHERE `tablekey_id` = 24
)) AS dead_rows

FROM `google_sort_tablekey` AS tablekey
JOIN `google_sort_backlink_domains` AS domain ON domain.tablekey_id = tablekey.id
WHERE domain.tablekey_id = 24

谁能帮我提高查询效率,以便它可以处理 google_sort_backlink_domains 表中的 100,000 多行?谢谢,麻烦您了!

4

1 回答 1

1

尝试更多类似的方法,将更多“恒定”计算放在变量中,并将子查询替换为聚合。

SET @id = 24;
SET @den = (SELECT SUM(1) FROM google_sort_backlink_domains);
SET @max = (SELECT MAX(checked) FROM google_sort_backlink_domains WHERE tablekey_id=@id);
SET @n = (SELECT 
              CASE 
                  WHEN processing_completed = 1 THEN 3 
                  WHEN MAX(checked) = 0 THEN 1 
                  ELSE MAX(checked) END 
          FROM google_sort_backlink_domains WHERE tablekey_id=@id);

SELECT 
    processing_completed AS complete,
    SUM(IF(link_found=1 OR checked>=@max, 1, 0)) / @den AS percent, 
    CASE 
        WHEN processing_completed=1 THEN 3 
        WHEN MAX(checked)=0 THEN 1 
        ELSE MAX(checked)
    END AS current_step,
    COUNT(back.id) AS total_rows,
    COUNT(domain.id) AS unique_domains,
    SUM(link_found) AS live_rows,
    SUM(IF(checked>= @n), 1, 0) AS dead_rows
FROM google_sort_tablekey AS tablekey 
JOIN google_sort_backlink AS back ON back.tablekey_id = tablekey.id
JOIN google_sort_backlink_domains AS domain ON domain.tablekey_id = tablekey.id
WHERE domain.tablekey_id = @id
GROUP BY processing_completed
于 2013-04-04T18:30:10.837 回答