选择需要很长时间。如何解决这个问题呢?

时间:2011-04-08 17:53:29

标签: mysql postgresql optimization memcached

我在MYSQL中有一个很大的基础 - 300 mb,其中有4个表:第一个是大约200mb,第二个是 - 80。 第一张表有150 000条记录,第二张有200 000条记录。

同时我在那里使用内连接。

当我使用优化和indeces时,选择需要3秒(之前需要大约20-30秒)。 这是足够好的结果。但我需要更多,因为页面加载7-8秒(选择3-4,计数1,另一个小查询1秒,1-2页面生成)。

那么,我应该做什么呢? postgres可能比mysql花费更少的时间?或者可能更好地使用memcaches,但在这种情况下它可能需要大量的内存(排序的变种太多)。

可能有人有另一个想法吗?我很高兴听到新的:)


行。我看到我们需要查询:) 我为table_1重命名了字段。

     CREATE TABLE  `table_1` (
      `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
      `field` varchar(2048) DEFAULT NULL,
      `field` varchar(2048) DEFAULT NULL,
      `field` int(10) unsigned DEFAULT NULL,
      `field` text,
      `field` text,
      `field` text,
      `field` varchar(128) DEFAULT NULL,
      `field` text,
      `field` text,
      `field` text,
      `field` text,
      `field` text,
      `field` varchar(128) DEFAULT NULL,
      `field` text,
      `field` varchar(4000) DEFAULT NULL,
      `field` varchar(4000) DEFAULT NULL,
      `field` int(10) unsigned DEFAULT '1',
      `field` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
      `field` text,
      `new` tinyint(1) NOT NULL DEFAULT '0',
      `applications` varchar(255) DEFAULT NULL,
      PRIMARY KEY (`id`),
      KEY `indexNA` (`new`,`applications`) USING BTREE
    ) ENGINE=InnoDB AUTO_INCREMENT=153235 DEFAULT CHARSET=utf8;

CREATE TABLE  `table_2` (
  `id_record` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `catalog_name` varchar(512) NOT NULL,
  `catalog_url` varchar(4000) NOT NULL,
  `parent_id` int(10) unsigned NOT NULL DEFAULT '0',
  `checked` tinyint(1) NOT NULL DEFAULT '0',
  `level` int(10) unsigned NOT NULL DEFAULT '0',
  `work` int(10) unsigned NOT NULL DEFAULT '0',
  `update` int(10) unsigned NOT NULL DEFAULT '1',
  `type` int(10) unsigned NOT NULL DEFAULT '0',
  `hierarchy` varchar(512) DEFAULT NULL,
  `synt` tinyint(1) NOT NULL DEFAULT '0',
  PRIMARY KEY (`id_record`,`type`) USING BTREE,
  KEY `rec` (`id_record`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=14504 DEFAULT CHARSET=utf8;

CREATE TABLE  `table_3` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `id_table_1` int(10) unsigned NOT NULL,
  `id_category` int(10) unsigned NOT NULL,
  `work` int(10) unsigned NOT NULL DEFAULT '1',
  `update` int(10) unsigned NOT NULL DEFAULT '1',
  PRIMARY KEY (`id`),
  KEY `site` (`id_table_1`,`id_category`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=203844 DEFAULT CHARSET=utf8;

有疑问: 1)获得一般计数(不到1秒):

SELECT count(table_1.id) FROM table_1
 INNER JOIN table_3 ON table_3.id_table_id = table_1.id
 INNER JOIN table_2 ON table_2.id_record = table_3.id_category
WHERE ((table_2.type = 0)
AND (table_3.work = 1 AND table_2.work = 1)
 AND (table_1.new = 1))AND 1 IN (table_1.applications)

2)获取有限制的页面列表(需要3到7秒,取决于计数):

SELECT table_1.field, table_1.field, table_1.field, table_1.field, table_2.catalog_name FROM table_1
 INNER JOIN table_3 ON table_3.id_table_id = table_1.id
 INNER JOIN table_2 ON table_2.id_record = table_3.id_category
WHERE ((table_2.type = 0)
AND (table_3.work = 1 AND table_2.work = 1)
 AND (table_1.new = 1))AND 1 IN (table_1.applications) LIMIT 10 OFFSET 10

6 个答案:

答案 0 :(得分:3)

不要更改DBMS

我不建议更改您的DBMS,它可能非常具有破坏性。如果您使用了与Postgres不兼容的MySQL特定查询;您可能需要重做整个索引等。即使这样,它也可能无法保证性能的提高。

缓存是一个不错的选择

缓存真的是个好主意。它会减轻您的DBMS负担。如果您有大量读取,轻写,则最适合。这样对象可以在Cache中保留更多时间。 MemcacheD是非常好的缓存机制,而且非常简单。快速扩展网站(如Facebook等)大量使用MemcacheD来减轻数据库的负担。

如何扩大真正的大时间

虽然,您没有非常繁重的数据..所以很可能缓存会对您有所帮助。但是,缓存之前的下一步是基于noSQL的解决方案,例如Cassandra。我们在我们的应用程序中使用cassandra,我们有大量的读写操作(50:50),数据库非常庞大且快速增长。卡桑德拉表现出色。但是,我想在你的情况下, Cassandra是一种矫枉过正的

<强>可是...

在此之前,您会深入研究任何严重的变化,我建议您真正研究索引。尝试垂直缩放。查看慢查询。 (搜索slow query logging指令)。希望MySQL在优化这些东西后会更快,你不需要额外的工具。

答案 1 :(得分:2)

您应该查看特定于您使用的最常见/最耗时的查询的索引。检查this post索引的mysql。

答案 2 :(得分:1)

除了其他人提供的所有其他建议外,我对MySQL的性能影响略有改变,并没有肯定。但是,我添加了STRAIGHT_JOIN,因此优化器不会尝试考虑为您加入哪个订单或表。

接下来,我将“AND”条件移动到表2和表2的相应JOIN子句中。 3。

最后,表1到3的连接(在你的帖子中)

   table_3.id_table_id = table_1.id

而不是

   table_3.id_table_1 = table_1.id

此外,我无法分辨性能,但可能只在“新”列上有一个独立的索引,以便完全匹配,而不考虑“应用程序”列。我不知道复合索引是否导致问题,因为您对应用程序使用“IN”而不是真正的可索引搜索基础。

这是修改后的结果

SELECT STRAIGHT_JOIN 
        count(table_1.id) 
    FROM 
        table_1
            JOIN table_3 
                ON table_1.id = table_3.id_table_1
                   AND table_3.work = 1
                JOIN table_2 
                    ON table_3.id_category = table_2.id_record
                    AND table_2.type = 0
                    AND table_2.work = 1
    WHERE 
            table_1.new = 1
        AND 1 IN table_1.applications


SELECT STRAIGHT_JOIN 
        table_1.field, 
        table_1.field, 
        table_1.field, 
        table_1.field, 
        table_2.catalog_name 
    FROM 
        table_1
            JOIN table_3 
                ON table_1.id = table_3.id_table_1
                AND table_3.work = 1
                JOIN table_2 
                    ON table_3.id_category = table_2.id_record
                    AND table_2.type = 0
                    AND table_2.work = 1
    WHERE 
            table_1.new = 1
        AND 1 IN table_1.applications
    LIMIT 10 OFFSET 10

答案 3 :(得分:0)

您还应优化查询。

答案 4 :(得分:0)

如果不仔细研究这些陈述,这个问题只能用理论方法来回答。只需要考虑一些想法......

SELECT-Statement ...

首先,确保您的查询尽可能“好”。你可能错过了任何可能吗?那些indeces是相同的字段类型等等吗?您是否可以缩小查询范围,以便数据库可以减少工作量?

查询缓存...

如果您的查询经常重复,可能有助于使用Query cache或 - 如果您已经在使用它 - 请为其提供更多内存。

硬件......

当然,不同的RDBMS比其他RDBMS更慢或更快,具体取决于它们的优势或劣势,但如果您的查询被优化为遗忘,您只能在扩展数据库服务器时更快地获得它(更好的cpu,更好的i / o等等,取决于瓶颈的位置)。

其他因素......

如果全部最大化,可能会尝试加速其他组件(1-2秒的页面生成对我来说看起来很慢)。

对于提及的所有因素,stackoverflow.com中有大量的想法和帖子。

答案 5 :(得分:0)

这实际上并不是一个如此庞大的数据库,对您的数据库系统来说肯定不会太多。作为比较,我们使用的数据库目前大约为40 GB。但它是一个MS SQL Server,所以它不能直接比较,但数据库系统之间没有显着差异。

我的猜测是你还没有完全成功地使用索引来加速查询。您应该查看查询的执行计划,看看是否可以发现大部分时间执行的执行部分。