【问题标题】:Select orderBy & limit slow for a table with 3,000,000 rows为具有 3,000,000 行的表选择 order By 并限制慢速
【发布时间】:2016-08-10 12:54:04
【问题描述】:

对于检索数据需要花费太多时间的查询,我需要帮助。

SELECT DISTINCT dataSet.professionalSid
FROM dataSet dataSet
INNER JOIN dataProfessional dataPro ON dataSet.sId=dataPro.dataSetSid
LEFT OUTER JOIN dataProfessional dataPro2  ON dataSet.sId=dataPro2.dataSetSid
AND (dataPro2.itemDefinitionId='PRO_NOM_EXERCICE'
     AND dataPro2.dataSetDefinitionId='DIRECTORY_PROFESSIONAL_RPPS')
WHERE dataSet.archive=0
  AND dataPro.dataSetDefinitionId='DIRECTORY_PROFESSIONAL_RPPS'
  AND (dataPro.itemDefinitionId IN ('PRO_PRENOM_EXERCICE'))
  AND MATCH(dataSet.searchIndex) AGAINST('+*p* ' IN BOOLEAN MODE)>=1
ORDER BY dataPro2.stringValue DESC LIMIT 10

dataProfessional表大约有370万行,dataSet大约有82万行,其他的表只是table def,只有5-10行。

此查询返回大约 28k 行,但我将其限制为 10。

索引:

表格数据集

+---------+------------+-----------------------------+--------------+--------------------------+-----------+-------------+----------+--------+------+------------+
|  Table  | Non_unique |          Key_name           | Seq_in_index |       Column_name        | Collation | Cardinality | Sub_part | Packed | Null | Index_type |
+---------+------------+-----------------------------+--------------+--------------------------+-----------+-------------+----------+--------+------+------------+
| dataSet |          0 | PRIMARY                     |            1 | sId                      | A         |      846564 | NULL     | NULL   |      | BTREE      |
| dataSet |          0 | sId                         |            1 | sId                      | A         |      846564 | NULL     | NULL   |      | BTREE      |
| dataSet |          1 | FK_dataSetDefinitionDataSet |            1 | dataSetDefinitionId      | A         |          70 | NULL     | NULL   |      | BTREE      |
| dataSet |          1 | FK_dataSetDefinitionDataSet |            2 | dataSetDefinitionVersion | A         |          76 | NULL     | NULL   |      | BTREE      |
| dataSet |          1 | FK_dataSetPatient           |            1 | patientSid               | A         |        2263 | NULL     | NULL   | YES  | BTREE      |
| dataSet |          1 | FK_dataSetProfessional      |            1 | professionalSid          | A         |      846564 | NULL     | NULL   | YES  | BTREE      |
| dataSet |          1 | FK_overrideDataSet          |            1 | overrideDataSetSid       | A         |           2 | NULL     | NULL   | YES  | BTREE      |
| dataSet |          1 | FullText                    |            1 | searchIndex              | NULL      |      846564 | NULL     | NULL   | YES  | FULLTEXT   |
+---------+------------+-----------------------------+--------------+--------------------------+-----------+-------------+----------+--------+------+------------+

表格数据专业

+------------------+------------+-------------------------------+--------------+--------------------------+-----------+-------------+----------+--------+------+------------+
|      Table       | Non_unique |           Key_name            | Seq_in_index |       Column_name        | Collation | Cardinality | Sub_part | Packed | Null | Index_type |
+------------------+------------+-------------------------------+--------------+--------------------------+-----------+-------------+----------+--------+------+------------+
| dataProfessional |          0 | PRIMARY                       |            1 | sId                      | A         |     3636911 | NULL     | NULL   |      | BTREE      |
| dataProfessional |          0 | sId                           |            1 | sId                      | A         |     3636911 | NULL     | NULL   |      | BTREE      |
| dataProfessional |          1 | FK_dataSetDataPro             |            1 | dataSetSid               | A         |     1818455 | NULL     | NULL   |      | BTREE      |
| dataProfessional |          1 | FK_itemDefinitionDataPro      |            1 | itemDefinitionVersion    | A         |           2 | NULL     | NULL   |      | BTREE      |
| dataProfessional |          1 | FK_itemDefinitionDataPro      |            2 | itemDefinitionId         | A         |        8172 | NULL     | NULL   |      | BTREE      |
| dataProfessional |          1 | FK_dataProfessionalDataSetDef |            1 | dataSetDefinitionId      | A         |         952 | NULL     | NULL   |      | BTREE      |
| dataProfessional |          1 | FK_dataProfessionalDataSetDef |            2 | dataSetDefinitionVersion | A         |         952 | NULL     | NULL   |      | BTREE      |
| dataProfessional |          1 | stringValue                   |            1 | stringValue              | A         |      909227 | 10       | NULL   | YES  | BTREE      |
+------------------+------------+-------------------------------+--------------+--------------------------+-----------+-------------+----------+--------+------+------------+

这是查询的解释:

+-----+-------------+----------+----------+---------------------------------------------------+-------------------+---------+----------------------------+------+----------------------------------------------+
|  id | select_type |  table   |   type   |                   possible_keys                   |        key        | key_len |            ref             | rows |                    Extra                     |
+-----+-------------+----------+----------+---------------------------------------------------+-------------------+---------+----------------------------+------+----------------------------------------------+
|   1 | SIMPLE      | dataSet  | fulltext | PRIMARY   sId   FullText                          | FullText          |       0 |                            |    1 | Using where; Using temporary; Using filesort |
|   1 | SIMPLE      | dataPro  | ref      | FK_dataSetDataPro   FK_dataProfessionalDataSetDef | FK_dataSetDataPro |       8 | cloud_dev_eret.dataSet.sId |    2 | Using where; Distinct                        |
|   1 | SIMPLE      | dataPro2 | ref      | FK_dataSetDataPro   FK_dataProfessionalDataSetDef | FK_dataSetDataPro |       8 | cloud_dev_eret.dataSet.sId |    2 | Using where; Distinct                        |
+-----+-------------+----------+----------+---------------------------------------------------+-------------------+---------+----------------------------+------+----------------------------------------------+

你知道我可以去哪里看吗? 如果您需要更多元素,请告诉我

谢谢

【问题讨论】:

  • dataPro2.stringValue 有索引吗?
  • 是的,我使用了这个命令'ALTER TABLE dataProfessional ADD INDEX stringValue (stringValue(10));'。
  • 您说该表有 300 万行。但是您的查询连接了多个表。那么哪个有300万,其他的大小是多少?另外,您的查询返回了多少行?当您在没有 order by 的情况下运行查询时,您实际上是获取 所有 行,还是仅根据获取前几行的时间来计时查询?
  • 我已经编辑并添加了更多元素,感谢您的帮助
  • 不完全重复,但答案仍然有效:stackoverflow.com/questions/38526528/…

标签: mysql sql database performance indexing


【解决方案1】:

我认为EXPLAIN 输出相当直截了当地告诉你所有你需要知道的。

我看到索引用于JOINs,但用于连接。我看不到任何可以帮助重要的条款,例如dataPro2.itemDefinitionId='PRO_NOM_EXERCICE'。我还看到了“全文”搜索,这可能会造成严重后果。

我也没有看到用于支持 ON dataSet.sId=dataPro2.dataSetSid"dataSetsid" 的索引。

简而言之,EXPLAIN 的输出可能说明了一切:您基本上是在进行蛮力搜索,候选行的数量可能确实非常庞大。 (例如如果 sId/dataSetSid 字段不是唯一的,导致 [部分] 笛卡尔积情况。)

【讨论】:

    【解决方案2】:

    “此查询返回大约 28k 行,但我将其限制为 10。” -- 由于查询的结构方式(FULLTEXTLEFTORDER BY 等),在到达ORDER BY & LIMIT 之前必须找到 28K 行。避免加速查询的唯一方法是缩小 28K 和/或加速单个片段。

    注意EXPLAIN 表示它以FULLTEXT 索引开头,忽略其他索引。 通常这是“正确”的做法。但不是AGAINST('+*p* ' IN BOOLEAN MODE)——这实际上是没有用的。您实际上是在寻找任何带有psearchIndex?这将是桌面的大部分内容。但使用索引需要付出额外的努力。

    这会更快,但仍然不快:searchIndex LIKE '%p%'

    通过计时并查看它们是否得到相同的计数来测试我所说的:

    SELECT DISTINCT COUNT(*)
        FROM dataSet
        WHERE MATCH(dataSet.searchIndex) AGAINST('+*p* ' IN BOOLEAN MODE)>=1;
    SELECT DISTINCT COUNT(*)
        FROM dataSet
        WHERE searchIndex LIKE '%p%';
    

    JOINdataPro 似乎没用;它的目的是什么?

    dataProfessional 需要INDEX(itemDefinitionId, dataSetDefinitionId, dataSetSid),顺序不限。

    LEFT JOIN 是否可以简单地称为JOIN

    *p*是用户生成的吗?考虑不允许这样。考虑把它变成我建议的%p%。考虑其他选项来避免这种缓慢的查询。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-08-17
      • 2011-07-19
      • 1970-01-01
      • 2016-01-18
      • 2018-10-18
      相关资源
      最近更新 更多