【问题标题】:mySQL >> Very Slow Query with CONCAT, GROUP_CONCAT and multiple JOINS (100 sec for 63 records)mySQL >> 使用 CONCAT、GROUP_CONCAT 和多个 JOINS 的非常慢的查询(63 条记录需要 100 秒)
【发布时间】:2018-03-24 19:19:40
【问题描述】:

我正在使用以下查询:

SELECT *,  
GROUP_CONCAT(distinct t_name order by t_id separator ', ') 'Topics', 
GROUP_CONCAT(distinct ch_title order by ch_id separator ', ') 'Chapters', 
GROUP_CONCAT(distinct cs_code order by cs_id separator ', ') 'ContentStandards', 
GROUP_CONCAT(distinct c_name order by c_id separator ', ') 'Categories', 
GROUP_CONCAT(distinct s_name order by s_id separator ', ') 'SchoolSubjects' 
FROM (
SELECT r.res_id, r.res_status, r.res_type, r.res_category, r.res_title, r.res_filename, r.res_source, r.res_gradelevel_from, r.res_gradelevel_to, r.res_tags, r.res_description, r.res_onserver, r.res_favoriteaccts, r.res_CreatedOn, c_id, s_id, t_id, ch_id, cs_id, 
CONCAT("<a class=""ReportLink"" href=""page.asp?category=",c_name,""" title=""",c_name,""">",c_name,"</a>") as c_name, 
CONCAT("<a class=""ReportLink"" href=""page.asp?subject=",s_name,""" title=""",s_name,""">",s_name,"</a>") as s_name, 
CONCAT("<a class=""ReportLink"" href=""page.asp?topic=",t_name,""" title=""",t_name,""">",t_name,"</a>") as t_name, 
CONCAT("<a class=""ReportLink"" href=""page.asp?cs=",cs_code,""" title=""",cs_code,""">",cs_code,"</a>") as cs_code, 
CONCAT("<a class=""ReportLink"" href=""page.asp?chapter=",ch_title,""" title=""",ch_title,""">",ch_code,": ",ch_title,"</a>") as ch_title 
FROM hre_resources r 
LEFT JOIN topic_to_resource ttr ON ttr.rt_resourceid = r.res_id 
LEFT JOIN topics t on t.t_id = ttr.rt_topicid 
LEFT JOIN topic_to_cs tcs on tcs.cst_topicid = t.t_id 
LEFT JOIN categories c ON c_id = r.res_category 
LEFT JOIN topic_to_framework ttc on ttc.ft_topicid = t.t_id 
LEFT JOIN ca_hss_frameworkchapters ch ON ch.ch_id = ttc.ft_frameworkid 
LEFT JOIN ca_hss_contentstandards cs ON cs.cs_id = tcs.cst_contentstandardid 
LEFT JOIN schoolsubjects_to_resource str ON str.sr_resid = r.res_id 
LEFT JOIN schoolsubjects s ON s.s_id = str.sr_sid) links 
WHERE RES_Status = 'Active' 
GROUP BY RES_ID 
ORDER BY RES_Title ASC, RES_Source DESC

此查询从我们的 mySQL DB 中返回 64 条格式完美的记录,但执行此操作需要 100 多秒。

查询分析器将主要违规者显示为:

+-------------------------------+-----------+
|         Sending data          | 34.530026 |
+-------------------------------+-----------+
| Creating sort index           | 24.205878 |
| Storing result in query cache | 56.739204 |
+-------------------------------+-----------+

EXPLAIN 结果如下:

+----+-------------+------------+--------+---------------+---------------+---------+------------------------------------+------+---------------------------------------------------------------------+
| id | select_type |   table    |  type  | possible_keys |      key      | key_len |                ref                 | rows |                                Extra                                |
+----+-------------+------------+--------+---------------+---------------+---------+------------------------------------+------+---------------------------------------------------------------------+
|  1 | PRIMARY     | <derived2> | ref    | <auto_key0>   | <auto_key0>   | 77      | const                              |   10 | Using index condition; Using where; Using temporary; Using filesort |
|  2 | DERIVED     | r          | ALL    | NULL          | NULL          | NULL    | NULL                               |   64 | NULL                                                                |
|  2 | DERIVED     | ttr        | ref    | RT_ResourceID | RT_ResourceID | 4       | uhri_hre.r.RES_ID                  |    3 | Using where                                                         |
|  2 | DERIVED     | t          | eq_ref | PRIMARY       | PRIMARY       | 4       | uhri_hre.ttr.RT_TopicID            |    1 | Using where                                                         |
|  2 | DERIVED     | tcs        | ref    | CST_TopicID   | CST_TopicID   | 4       | uhri_hre.t.T_ID                    |    9 | Using where                                                         |
|  2 | DERIVED     | c          | eq_ref | PRIMARY       | PRIMARY       | 4       | uhri_hre.r.RES_Category            |    1 | Using where                                                         |
|  2 | DERIVED     | ttc        | ref    | FT_TopicID    | FT_TopicID    | 4       | uhri_hre.t.T_ID                    |   21 | Using where                                                         |
|  2 | DERIVED     | ch         | eq_ref | PRIMARY       | PRIMARY       | 4       | uhri_hre.ttc.FT_FrameworkID        |    1 | Using where                                                         |
|  2 | DERIVED     | cs         | eq_ref | PRIMARY       | PRIMARY       | 4       | uhri_hre.tcs.CST_ContentStandardID |    1 | Using where                                                         |
|  2 | DERIVED     | str        | ref    | SR_RESID      | SR_RESID      | 4       | uhri_hre.r.RES_ID                  |    1 | Using where                                                         |
|  2 | DERIVED     | s          | eq_ref | PRIMARY       | PRIMARY       | 4       | uhri_hre.str.SR_SID                |    1 | Using where                                                         |
+----+-------------+------------+--------+---------------+---------------+---------+------------------------------------+------+---------------------------------------------------------------------+

这些表具有以下索引。未列出的表在 ID 字段(主键)上有索引:

HRE_Resources:
+--------------+-------+--------+--------+--------------+-------------+-----------+------+---------+
|   Keyname    | Type  | Unique | Packed |    Column    | Cardinality | Collation | Null | Comment |
+--------------+-------+--------+--------+--------------+-------------+-----------+------+---------+
| PRIMARY      | BTREE | Yes    | No     | RES_ID       |          64 | A         |      |         |
| RES_Type     | BTREE | No     | No     | RES_Type     |           4 | A         |      |         |
| RES_Category | BTREE | No     | No     | RES_Category |          10 | A         |      |         |
| RES_Status   | BTREE | No     | No     | RES_Status   |           4 | A         |      |         |
| RES_Language | BTREE | No     | No     | RES_Language |           8 | A         |      |         |
| RES_Source   | BTREE | No     | No     | RES_Source   |          21 | A         |      |         |
+--------------+-------+--------+--------+--------------+-------------+-----------+------+---------+

Topics:
+---------+-------+--------+--------+--------+-------------+-----------+------+---------+
| Keyname | Type  | Unique | Packed | Column | Cardinality | Collation | Null | Comment |
+---------+-------+--------+--------+--------+-------------+-----------+------+---------+
| PRIMARY | BTREE | Yes    | No     | T_ID   |          39 | A         |      |         |
| T_Name  | BTREE | No     | No     | T_Name |          39 | A         |      |         |
+---------+-------+--------+--------+--------+-------------+-----------+------+---------+

Topic_to_CS:
+-----------------------+-------+--------+--------+-----------------------+-------------+-----------+------+---------+
|        Keyname        | Type  | Unique | Packed |        Column         | Cardinality | Collation | Null | Comment |
+-----------------------+-------+--------+--------+-----------------------+-------------+-----------+------+---------+
| PRIMARY               | BTREE | Yes    | No     | CST_ID                |         685 | A         |      |         |
| CST_ContentStandardID | BTREE | No     | No     | CST_ContentStandardID |         228 | A         |      |         |
| CST_TopicID           | BTREE | No     | No     | CST_TopicID           |          76 | A         |      |         |
+-----------------------+-------+--------+--------+-----------------------+-------------+-----------+------+---------+

Topic_to_Framework:
+----------------+-------+--------+--------+----------------+-------------+-----------+------+---------+
|    Keyname     | Type  | Unique | Packed |     Column     | Cardinality | Collation | Null | Comment |
+----------------+-------+--------+--------+----------------+-------------+-----------+------+---------+
| PRIMARY        | BTREE | Yes    | No     | FT_ID          |         471 | A         |      |         |
| FT_TopicID     | BTREE | No     | No     | FT_TopicID     |          22 | A         |      |         |
| FT_FrameworkID | BTREE | No     | No     | FT_FrameworkID |         235 | A         |      |         |
+----------------+-------+--------+--------+----------------+-------------+-----------+------+---------+

Topic_to_Resource:
+---------------+-------+--------+--------+---------------+-------------+-----------+------+---------+
|    Keyname    | Type  | Unique | Packed |    Column     | Cardinality | Collation | Null | Comment |
+---------------+-------+--------+--------+---------------+-------------+-----------+------+---------+
| PRIMARY       | BTREE | Yes    | No     | RT_ID         |         387 | A         |      |         |
| RT_ResourceID | BTREE | No     | No     | RT_ResourceID |         129 | A         |      |         |
| RT_TopicID    | BTREE | No     | No     | RT_TopicID    |          77 | A         |      |         |
+---------------+-------+--------+--------+---------------+-------------+-----------+------+---------+

Schoolsubject_to_Resource:
+----------+-------+--------+--------+----------+-------------+-----------+------+---------+
| Keyname  | Type  | Unique | Packed |  Column  | Cardinality | Collation | Null | Comment |
+----------+-------+--------+--------+----------+-------------+-----------+------+---------+
| PRIMARY  | BTREE | Yes    | No     | SR_ID    |         228 | A         |      |         |
| SR_SID   | BTREE | No     | No     | SR_SID   |          25 | A         |      |         |
| SR_RESID | BTREE | No     | No     | SR_RESID |         228 | A         |      |         |
+----------+-------+--------+--------+----------+-------------+-----------+------+---------+

Categories:
+---------+-------+--------+--------+--------+-------------+-----------+------+---------+
| Keyname | Type  | Unique | Packed | Column | Cardinality | Collation | Null | Comment |
+---------+-------+--------+--------+--------+-------------+-----------+------+---------+
| PRIMARY | BTREE | Yes    | No     | C_ID   |           9 | A         |      |         |
| C_Name  | BTREE | No     | No     | C_Name |           9 | A         |      |         |
+---------+-------+--------+--------+--------+-------------+-----------+------+---------+

其中一些索引是使用其他查询中使用的更复杂的 WHERE 创建的。

我已经在数据库上运行了与上述查询无关的其他目的的复杂查询,并且名义上执行。因此,我认为这不是服务器资源问题。

任何人都可以在上面的查询中看到任何可能导致响应如此缓慢的内容吗?

非常感谢!

PS。根据以下请求从服务器添加一些信息...

+------------------------------+---------+
|        Variable_name         |  Value  |
+------------------------------+---------+
| query_alloc_block_size       | 8192    |
| query_cache_limit            | 1048576 |
| query_cache_min_res_unit     | 4096    |
| query_cache_size             | 1048576 |
| query_cache_type             | ON      |
| query_cache_wlock_invalidate | OFF     |
| query_prealloc_size          | 8192    |
+------------------------------+---------+

+-------------------------+--------+
|      Variable_name      | Value  |
+-------------------------+--------+
| Qcache_free_blocks      |      9 |
| Qcache_free_memory      |  22736 |
| Qcache_hits             | 121910 |
| Qcache_inserts          |   9296 |
| Qcache_lowmem_prunes    |   8213 |
| Qcache_not_cached       |  29475 |
| Qcache_queries_in_cache |    103 |
| Qcache_total_blocks     |    295 |
+-------------------------+--------+

【问题讨论】:

  • 你检查过子查询的结果数吗?我的猜测是你有几个不相关的一对多关系,它们相互乘以各自的结果......而你的 GROUP_CONCAT 中的 DISTINCT 隐藏了这一点。
  • ...如果是这种情况,通常的做法是将这些连接分解为最小的子查询,然后将它们连接在一起以获得相同的最终结果格式。
  • 我同意。不要试图在一个查询中完成所有操作。这会产生巨大的笛卡尔积,然后你必须使用 DISTINCT 减少它。相反,只需运行几个查询,这些查询单独起来更简单。
  • 另外,我建议您不要在 SQL 查询中格式化 HTML。只需取回数据,并使用应用程序代码以 HTML 形式呈现数据值。
  • 我还注意到您的查询花费了 50% 的时间来更新查询缓存。我建议您禁用查询缓存。由于这种事情,MySQL 8.0 中删除了查询缓存功能。

标签: mysql performance join indexing group-concat


【解决方案1】:

正如我在上面的 cmets 中提到的,您似乎正在从多个表关系中获取大量数据。这会导致多个Cartesian products,这就是您获得 626K 行的原因。

解决方案是将其分解为单独的查询。

以下是我对您的模型的理解:

以下是各个查询的外观,以及它们各自的 EXPLAIN 计划。

您可以看到,这消除了所有子查询和临时表,消除了笛卡尔积,因此您无需在任何地方使用 DISTINCT,并且所有连接都很好地针对主键。这似乎是重复的,但查询得到更好的优化这一事实应该会使其运行得更快。

EXPLAIN
SELECT r.res_id, r.res_status, r.res_type, r.res_category, r.res_title, r.res_filename,
  r.res_source, r.res_gradelevel_from, r.res_gradelevel_to, r.res_tags, r.res_description,
  r.res_onserver, r.res_favoriteaccts, r.res_CreatedOn, c.c_name AS 'Categories'
FROM hre_resources AS r
INNER JOIN categories c ON c_id = r.res_category 
WHERE r.res_status = 'Active'
--------------

+----+-------------+-------+--------+-------------------------+------------+---------+---------------------+------+-----------------------+
| id | select_type | table | type   | possible_keys           | key        | key_len | ref                 | rows | Extra                 |
+----+-------------+-------+--------+-------------------------+------------+---------+---------------------+------+-----------------------+
|  1 | SIMPLE      | r     | ref    | res_status,res_category | res_status | 1       | const               |    1 | Using index condition |
|  1 | SIMPLE      | c     | eq_ref | PRIMARY                 | PRIMARY    | 4       | test.r.res_category |    1 | NULL                  |
+----+-------------+-------+--------+-------------------------+------------+---------+---------------------+------+-----------------------+

EXPLAIN
SELECT r.res_id, GROUP_CONCAT(s.s_name ORDER BY s.s_id SEPARATOR ', ') AS 'SchoolSubjects' 
FROM hre_resources AS r
INNER JOIN schoolsubjects_to_resource str ON str.sr_resid = r.res_id 
INNER JOIN schoolsubjects s ON s.s_id = str.sr_sid
WHERE r.res_status = 'Active' 
GROUP BY r.res_id
--------------

+----+-------------+-------+--------+---------------------------------+------------+---------+-----------------+------+--------------------------+
| id | select_type | table | type   | possible_keys                   | key        | key_len | ref             | rows | Extra                    |
+----+-------------+-------+--------+---------------------------------+------------+---------+-----------------+------+--------------------------+
|  1 | SIMPLE      | r     | ref    | PRIMARY,res_status,res_category | res_status | 1       | const           |    1 | Using where; Using index |
|  1 | SIMPLE      | str   | ref    | PRIMARY,sr_sid                  | PRIMARY    | 4       | test.r.res_id   |    1 | Using index              |
|  1 | SIMPLE      | s     | eq_ref | PRIMARY                         | PRIMARY    | 4       | test.str.sr_sid |    1 | NULL                     |
+----+-------------+-------+--------+---------------------------------+------------+---------+-----------------+------+--------------------------+
3 rows in set (0.00 sec)

--------------
EXPLAIN
SELECT r.res_id, GROUP_CONCAT(t.t_name ORDER BY t_id SEPARATOR ', ') AS 'Topics'
FROM hre_resources AS r
INNER JOIN topic_to_resource ttr ON ttr.rt_resourceid = r.res_id 
INNER JOIN topics t on t.t_id = ttr.rt_topicid 
WHERE r.res_status = 'Active' 
GROUP BY r.res_id
--------------

+----+-------------+-------+--------+---------------------------------+------------+---------+---------------------+------+--------------------------+
| id | select_type | table | type   | possible_keys                   | key        | key_len | ref                 | rows | Extra                    |
+----+-------------+-------+--------+---------------------------------+------------+---------+---------------------+------+--------------------------+
|  1 | SIMPLE      | r     | ref    | PRIMARY,res_status,res_category | res_status | 1       | const               |    1 | Using where; Using index |
|  1 | SIMPLE      | ttr   | ref    | PRIMARY,rt_topicid              | PRIMARY    | 4       | test.r.res_id       |    1 | Using index              |
|  1 | SIMPLE      | t     | eq_ref | PRIMARY                         | PRIMARY    | 4       | test.ttr.rt_topicid |    1 | NULL                     |
+----+-------------+-------+--------+---------------------------------+------------+---------+---------------------+------+--------------------------+
3 rows in set (0.00 sec)

--------------
EXPLAIN
SELECT r.res_id, GROUP_CONCAT(DISTINCT CONCAT(ch.ch_code, ':', ch.ch_title) ORDER BY ch.ch_id SEPARATOR ', ') AS 'Chapters'
FROM hre_resources AS r
INNER JOIN topic_to_resource ttr ON ttr.rt_resourceid = r.res_id 
INNER JOIN topics t on t.t_id = ttr.rt_topicid 
INNER JOIN topic_to_framework ttc on ttc.ft_topicid = t.t_id 
INNER JOIN ca_hss_frameworkchapters ch ON ch.ch_id = ttc.ft_frameworkid 
WHERE r.res_status = 'Active' 
GROUP BY r.res_id
--------------

+----+-------------+-------+--------+---------------------------------+------------+---------+-------------------------+------+--------------------------+
| id | select_type | table | type   | possible_keys                   | key        | key_len | ref                     | rows | Extra                    |
+----+-------------+-------+--------+---------------------------------+------------+---------+-------------------------+------+--------------------------+
|  1 | SIMPLE      | r     | ref    | PRIMARY,res_status,res_category | res_status | 1       | const                   |    1 | Using where; Using index |
|  1 | SIMPLE      | ttr   | ref    | PRIMARY,rt_topicid              | PRIMARY    | 4       | test.r.res_id           |    1 | Using index              |
|  1 | SIMPLE      | t     | eq_ref | PRIMARY                         | PRIMARY    | 4       | test.ttr.rt_topicid     |    1 | Using index              |
|  1 | SIMPLE      | ttc   | ref    | PRIMARY,ft_frameworkid          | PRIMARY    | 4       | test.ttr.rt_topicid     |    1 | Using index              |
|  1 | SIMPLE      | ch    | eq_ref | PRIMARY                         | PRIMARY    | 4       | test.ttc.ft_frameworkid |    1 | NULL                     |
+----+-------------+-------+--------+---------------------------------+------------+---------+-------------------------+------+--------------------------+
5 rows in set (0.00 sec)

--------------
EXPLAIN
SELECT r.res_id, GROUP_CONCAT(DISTINCT cs.cs_code ORDER BY cs.cs_id SEPARATOR ', ') AS 'ContentStandards'
FROM hre_resources AS r
INNER JOIN topic_to_resource ttr ON ttr.rt_resourceid = r.res_id 
INNER JOIN topics t on t.t_id = ttr.rt_topicid 
INNER JOIN topic_to_cs tcs on tcs.cst_topicid = t.t_id 
INNER JOIN ca_hss_contentstandards cs ON cs.cs_id = tcs.cst_contentstandardid 
WHERE r.res_status = 'Active' 
GROUP BY r.res_id
--------------

+----+-------------+-------+--------+---------------------------------+------------+---------+--------------------------------+------+--------------------------+
| id | select_type | table | type   | possible_keys                   | key        | key_len | ref                            | rows | Extra                    |
+----+-------------+-------+--------+---------------------------------+------------+---------+--------------------------------+------+--------------------------+
|  1 | SIMPLE      | r     | ref    | PRIMARY,res_status,res_category | res_status | 1       | const                          |    1 | Using where; Using index |
|  1 | SIMPLE      | ttr   | ref    | PRIMARY,rt_topicid              | PRIMARY    | 4       | test.r.res_id                  |    1 | Using index              |
|  1 | SIMPLE      | t     | eq_ref | PRIMARY                         | PRIMARY    | 4       | test.ttr.rt_topicid            |    1 | Using index              |
|  1 | SIMPLE      | tcs   | ref    | PRIMARY,cst_contentstandardid   | PRIMARY    | 4       | test.ttr.rt_topicid            |    1 | Using index              |
|  1 | SIMPLE      | cs    | eq_ref | PRIMARY                         | PRIMARY    | 4       | test.tcs.cst_contentstandardid |    1 | NULL                     |
+----+-------------+-------+--------+---------------------------------+------------+---------+--------------------------------+------+--------------------------+

下面是我为表格假设的 DDL。如果您将其包含在原始问题中,那将会很有帮助。

CREATE TABLE categories (
    c_id INT PRIMARY KEY,
    c_name VARCHAR(100) NOT NULL DEFAULT 'c_name'
);

CREATE TABLE hre_resources (
    res_id INT PRIMARY KEY,
    res_category INT NOT NULL,
    res_status ENUM('Active', 'Inactive') NOT NULL DEFAULT 'Active',
    res_type VARCHAR(100) NOT NULL DEFAULT 'type',
    res_title VARCHAR(100) NOT NULL DEFAULT 'title',
    res_filename VARCHAR(100) NOT NULL DEFAULT '',
    res_source VARCHAR(100) NOT NULL DEFAULT '',
    res_gradelevel_from VARCHAR(100) NOT NULL DEFAULT '',
    res_gradelevel_to VARCHAR(100) NOT NULL DEFAULT '',
    res_tags VARCHAR(100) NOT NULL DEFAULT '',
    res_description VARCHAR(100) NOT NULL DEFAULT '',
    res_onserver VARCHAR(100) NOT NULL DEFAULT '',
    res_favoriteaccts VARCHAR(100) NOT NULL DEFAULT '',
    res_CreatedOn DATE NOT NULL DEFAULT '2017-01-01',
    KEY (res_status),
    FOREIGN KEY (res_category) REFERENCES categories(c_id)
);

CREATE TABLE topics (
    t_id INT PRIMARY KEY,
    t_name VARCHAR(100) NOT NULL DEFAULT 't_name'
);

CREATE TABLE ca_hss_frameworkchapters (
    ch_id INT PRIMARY KEY,
    ch_title VARCHAR(100) NOT NULL DEFAULT 'ch_title',
    ch_code VARCHAR(100) NOT NULL DEFAULT 'ch_code'
);

CREATE TABLE ca_hss_contentstandards (
    cs_id INT PRIMARY KEY,
    cs_code VARCHAR(100) NOT NULL DEFAULT 'cs_code'
);

CREATE TABLE schoolsubjects (
    s_id INT PRIMARY KEY,
    s_name VARCHAR(100) NOT NULL DEFAULT 's_name'
);

CREATE TABLE topic_to_framework (
    ft_topicid INT NOT NULL,
    ft_frameworkid INT NOT NULL,
    PRIMARY KEY (ft_topicid, ft_frameworkid),
    FOREIGN KEY (ft_topicid) REFERENCES topics(t_id),
    FOREIGN KEY (ft_frameworkid) REFERENCES ca_hss_frameworkchapters(ch_id)
);

CREATE TABLE topic_to_resource (
    rt_resourceid INT NOT NULL,
    rt_topicid INT NOT NULL,
    PRIMARY KEY (rt_resourceid, rt_topicid),
    FOREIGN KEY (rt_resourceid) REFERENCES hre_resources (res_id),
    FOREIGN KEY (rt_topicid) REFERENCES topics(t_id)
);

CREATE TABLE topic_to_cs (
    cst_topicid INT NOT NULL,
    cst_contentstandardid INT NOT NULL,
    PRIMARY KEY (cst_topicid, cst_contentstandardid),
    FOREIGN KEY (cst_topicid) REFERENCES topics(t_id),
    FOREIGN KEY (cst_contentstandardid) REFERENCES ca_hss_contentstandards(cs_id)
);

CREATE TABLE schoolsubjects_to_resource (
    sr_resid INT NOT NULL,
    sr_sid INT NOT NULL,
    PRIMARY KEY (sr_resid, sr_sid),
    FOREIGN KEY (sr_resid) REFERENCES hre_resources(res_id),
    FOREIGN KEY (sr_sid) REFERENCES schoolsubjects(s_id)
);

这是一个 Python 示例,我的意思是将多个查询的结果合并在一起。

import pprint
import MySQLdb
import MySQLdb.cursors

db = MySQLdb.connect(host="localhost", db="test", cursorclass=MySQLdb.cursors.DictCursor)
cur = db.cursor()

res_data = {}

sql = """SELECT r.res_id, r.res_status, r.res_type, r.res_category, r.res_title, r.res_filename, r.res_source, r.res_gradelevel_from, r.res_gradelevel_to, r.res_tags, r.res_description,  r.res_onserver, r.res_favoriteaccts, r.res_CreatedOn, c.c_name AS 'Categories' FROM hre_resources AS r INNER JOIN categories c ON c_id = r.res_category WHERE r.res_status = 'Active'"""
cur.execute(sql)
for row in cur.fetchall():
  res_data[row['res_id']] = row

sql = """SELECT r.res_id, GROUP_CONCAT(s.s_name ORDER BY s.s_id SEPARATOR ', ') AS 'SchoolSubjects' FROM hre_resources AS r INNER JOIN schoolsubjects_to_resource str ON str.sr_resid = r.res_id  INNER JOIN schoolsubjects s ON s.s_id = str.sr_sid WHERE r.res_status = 'Active' GROUP BY r.res_id"""
cur.execute(sql)
for row in cur.fetchall():
  res_data[row['res_id']].update(row)

sql = """SELECT r.res_id, GROUP_CONCAT(t.t_name ORDER BY t_id SEPARATOR ', ') AS 'Topics' FROM hre_resources AS r INNER JOIN topic_to_resource ttr ON ttr.rt_resourceid = r.res_id INNER JOIN topics t on t.t_id = ttr.rt_topicid WHERE r.res_status = 'Active' GROUP BY r.res_id"""
cur.execute(sql)
for row in cur.fetchall():
  res_data[row['res_id']].update(row)

sql = """SELECT r.res_id, GROUP_CONCAT(DISTINCT CONCAT(ch.ch_code, ':', ch.ch_title) ORDER BY ch.ch_id SEPARATOR ', ') AS 'Chapters' FROM hre_resources AS r INNER JOIN topic_to_resource ttr ON ttr.rt_resourceid = r.res_id INNER JOIN topics t on t.t_id = ttr.rt_topicid INNER JOIN topic_to_framework ttc on ttc.ft_topicid = t.t_id INNER JOIN ca_hss_frameworkchapters ch ON ch.ch_id = ttc.ft_frameworkid WHERE r.res_status = 'Active' GROUP BY r.res_id"""
cur.execute(sql)
for row in cur.fetchall():
  res_data[row['res_id']].update(row)

sql = """SELECT r.res_id, GROUP_CONCAT(DISTINCT cs.cs_code ORDER BY cs.cs_id SEPARATOR ', ') AS 'ContentStandards' FROM hre_resources AS r INNER JOIN topic_to_resource ttr ON ttr.rt_resourceid = r.res_id INNER JOIN topics t on t.t_id = ttr.rt_topicid INNER JOIN topic_to_cs tcs on tcs.cst_topicid = t.t_id INNER JOIN ca_hss_contentstandards cs ON cs.cs_id = tcs.cst_contentstandardid WHERE r.res_status = 'Active' GROUP BY r.res_id"""
cur.execute(sql)
for row in cur.fetchall():
  res_data[row['res_id']].update(row)

db.close()

pp = pprint.PrettyPrinter()
pp.pprint(res_data)

在每个表中添加一行假数据后,我从上面的脚本中得到了这个输出:

{2L: {'Categories': 'c_name',
      'Chapters': 'ch_codech_title',
      'ContentStandards': 'cs_code',
      'SchoolSubjects': 's_name',
      'Topics': 't_name',
      'res_CreatedOn': datetime.date(2017, 1, 1),
      'res_category': 1L,
      'res_description': '',
      'res_favoriteaccts': '',
      'res_filename': '',
      'res_gradelevel_from': '',
      'res_gradelevel_to': '',
      'res_id': 2L,
      'res_onserver': '',
      'res_source': '',
      'res_status': 'Active',
      'res_tags': '',
      'res_title': 'title',
      'res_type': 'type'}}

【讨论】:

  • 非常感谢,比尔!我没有包含 CREATE TABLES 的原因是 hre_resource 表要大得多。该表中有很多数据未用于此视图。回复:您的解决方案,我如何将它们包装在一起,以便在将其写入页面时循环单个记录集?
  • 是的,这就是我上面的 Python 代码示例所做的。使用 Python 的 dict.update() 方法将每个查询结果与相同 res_id 的行组合在一起。你可以用任何其他语言做类似的事情,我不知道你使用的是什么语言。
  • 对不起,兄弟,我得去学校接孩子了。我非常感谢您的帮助,并很高兴为您提供应有的帮助!干杯,N
  • 我想这是对 DISTINCT 的更好使用。它不应该那么昂贵,因为它不必在 626K 行上工作。替代方案:编写应用程序代码以使用哈希映射减少重复项。
  • @nbardach,已修复。我还为章节查询修复了CONCAT(ch.ch_code, ':', ch.ch_title)。代码和标题之间需要一些分隔符。
【解决方案2】:

首先将WHERE RES_Status = 'Active' 拉到派生表中。这可能会显着减小 tmp 表的大小,并可能显着缩短“创建排序索引”阶段。

然后关注派生表。把它分开。需要多长时间?

至于56.7s部分,听起来有些设置太高了。请提供:

SHOW VARIABLES LIKE 'query%';
SHOW GLOBAL STATUS LIKE 'Qc%';

【讨论】:

  • 看起来所有的查询缓存设置都是默认的,除了它是打开的。正如我在顶部的评论中所说,我会设置 query_cache_type=0query_cache_size=0 来禁用它。
  • 嗯...SHOWs 无法解释 56.7s。正如比尔建议的那样,关闭 QC。至于 626K 行,您是否使用 JOIN 而不是 LEFT JOIN 得到“正确”答案? 子查询开始一个新问题。
猜你喜欢
  • 2015-04-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多