【问题标题】:What is the best optimization for this table and its queries?此表及其查询的最佳优化是什么?
【发布时间】:2015-09-29 22:43:24
【问题描述】:

我有这张桌子:

CREATE TABLE IF NOT EXISTS `listings` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `type` tinyint(1) NOT NULL DEFAULT '1',
  `hash` char(32) NOT NULL,
  `source_id` int(10) unsigned NOT NULL,
  `link` varchar(255) NOT NULL,
  `short_link` varchar(255) NOT NULL,
  `cat_id` mediumint(5) NOT NULL,
  `title` mediumtext NOT NULL,
  `description` mediumtext,
  `content` mediumtext,
  `images` mediumtext,
  `videos` mediumtext,
  `views` int(10) NOT NULL,
  `comments` int(11) NOT NULL DEFAULT '0',
  `comments_update` int(11) NOT NULL DEFAULT '0',
  `editor_id` int(11) NOT NULL DEFAULT '0',
  `auther_name` varchar(255) DEFAULT NULL,
  `createdby_id` int(10) NOT NULL,
  `createdon` int(20) NOT NULL,
  `editedby_id` int(10) NOT NULL,
  `editedon` int(20) NOT NULL,
  `deleted` tinyint(1) NOT NULL,
  `deletedon` int(20) NOT NULL,
  `deletedby_id` int(10) NOT NULL,
  `deletedfor` varchar(255) NOT NULL,
  `published` tinyint(1) NOT NULL DEFAULT '1',
  `publishedon` int(20) NOT NULL,
  `publishedby_id` int(10) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `hash` (`hash`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT AUTO_INCREMENT=91628 ;

还有一些像这样的错误查询

SELECT  id,type , source_id, link, short_link, cat_id, title,
        description, images, views, comments, published, publishedon,
        content, comments_update, editor_id, auther_name, createdby_id,
        createdon, editedby_id, editedon, deleted, deletedon,
        deletedby_id, deletedfor, publishedby_id
    FROM  listings
    WHERE  (cat_id IN ( 98 ))
      AND  (TYPE IN ('1'))
      AND  (source_id IN ('78'))AND (FROM_UNIXTIME( publishedon ) >= SUBDATE( NOW( ) ,
                        1 )
           )
      AND  (deleted =0)
      AND  (published =1)
    ORDER BY  `publishedon` DESC
    LIMIT  10 OFFSET 0 

SELECT  id,type,source_id,link,short_link,cat_id,title,description,
       images,views,comments,published,publishedon
    FROM  listings
    WHERE  (title RLIKE 'اليمن|عدن')
      AND  (id != 89024)
      AND  (deleted = 0)
      AND  (published = 1)
    ORDER BY  publishedon DESC
    LIMIT  6 OFFSET 0 

SELECT MIN(id) FROM listings
    WHERE (id > 91152) AND (cat_id = '134')

SELECT  COUNT(id)
    FROM  listings
    WHERE  (publishedon >= '1442963362'
              AND  publishedon <= '1443568162'
           )
      AND  (cat_id IN ('19', '20', '21', '22', '23', '24', '27',
                        '32', '35', '110', '54', '38', '39', '41', '42', '43',
                        '44', '45', '46', '47', '49', '56', '57', '51', '55',
                        '58', '59', '60', '61', '62', '102', '95', '96', '98',
                        '101', '103', '104', '105', '106', '124', '125', '130',
                        '131', '132', '133', '134', '135')
           ) 

此查询可能需要 0.4 秒才能完成。任何在一页中都可能包含 5 个这样的查询。这是一个很大的问题;它会导致服务器加载和停机。

这个查询

SELECT *
FROM `listings`
WHERE id = 5455

需要 0.0004 秒才能完成,因为它取决于 pk 的索引

如何为第一个查询中的列创建索引?

而且很多时候,当我使用“show processlist”时,我看到这个“Waiting for table level lock”太多和“sorting data”。

应用程序一直插入/更新许多行;我该如何解决?

【问题讨论】:

  • SELECT 语句不可读; WHERE 中的条件子句不应该分布在这么多行上,但顶部的选择列表应该分布在几行上,这样就可以在不水平滚动的情况下阅读它。

标签: mysql indexing query-optimization


【解决方案1】:

您的查询基本上是:

SELECT . . .
FROM listings l
WHERE cat_id = 98 AND
      TYPE = 1 AND
      source_id = 78 AND
      deleted = 0 AND
      published = 1 AND
      FROM_UNIXTIME( publishedon ) >= SUBDATE( NOW( ) , 1 )
ORDER BY `publishedon` DESC
LIMIT 10
OFFSET 0 

为了提高性能,从(cat_id, type, source_id, deleted, published, publishedon) 上的复合索引开始。语法是:

create index idx_listings_6 on listings(cat_id, type, source_id, deleted, published, publishedon desc);

接下来,我建议将where 子句重写为:

SELECT . . .
FROM listings l
WHERE cat_id = 98 AND
      TYPE = 1 AND
      source_id = 78 AND
      deleted = 0 AND
      published = 1 AND
      publishedon >= UNIX_TIMESTAMP(SUBDATE( NOW( ) , 1 ))
ORDER BY `publishedon` DESC
LIMIT 10
OFFSET 0 

并使用上面相同的索引。

【讨论】:

  • 这会影响执行时间吗?你的意思是为这些列建立索引吗?与 btree?
  • ALTER TABLE listings ADD INDEX someIndexName (cat_id, type, source_id, deleted, published, publishedon)
  • 只有当我删除 ORDER BY publishedon DESC 时它才能快速工作,有什么解释吗?
  • @UnixMan 。 . .尝试使用第二个版本的查询。我还更改了索引,因此publishedon 在索引中下降。这可能有助于 MySQL 使用 whereorder by 的索引(这是最佳性能所必需的)。
  • 我可以创建其他索引,例如在列表上创建索引 idx_listings_7(cat_id、type、source_id、deleted、published、views desc);并在列表上创建索引 idx_listings_6(cat_id, type, id desc);等等,或者这很糟糕
【解决方案2】:

MySQL 不能将索引声明为DESC;它忽略该关键字并建立一个ASC 索引。但是,ORDER BY x DESC 仍然可以优化。

MySQL 每个 SELECT 将只使用一个 INDEX。 (通常)。

最佳索引以任何带有 '=' 的 WHERE 子句字段开头。

问题 1:已经讨论过。

查询 2:INDEX(deleted, published, publishedon)

查询 3:INDEX(cat_id, id)

查询 4:将 COUNT(id) 更改为 COUNT(*) 并添加 INDEX(cat_id, publishedon) 和/或 INDEX(publishedon, cat_id)。哪个指数更好还不清楚。添加两者并让优化器决定。与您的另一个问题一样,PARTITION BY RANGE(publishedon) 并使用INDEX(cat_id, publishedon)(不是另一个)可能会有所帮助。

考虑切换到 InnoDB。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-19
    • 2012-07-14
    • 1970-01-01
    • 1970-01-01
    • 2010-11-14
    • 1970-01-01
    相关资源
    最近更新 更多