我有这个表(500,000行)
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) unsigned NOT NULL,`comments` int(11) 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(11) unsigned NOT NULL,`publishedby_id` int(10) NOT NULL,PRIMARY KEY (`id`),KEY `hash` (`hash`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8;

我正在考虑在x和y之间发布每个查询(在所有网站上显示只有1个月的记录)

在同一时间,我想添加与publishedon在where子句发布,cat_id,source_id

这样的事情

SELECT * FROM listings 
WHERE (publishedon BETWEEN 1441105258 AND 1443614458) 
  AND (published = 1) 
  AND (cat_id in(1,2,3,4,5)) 
  AND (source_id  in(1,5))

那个查询是确定的,直到现在没有索引,但是当尝试使用orderon,它变得太慢,所以我使用这个索引

CREATE INDEX `listings_pcs` ON listings(
    `publishedon` DESC,`published`,`cat_id`,`source_id`
)

它的工作和发布的顺序变得很快,现在我想通过这样的意见订购

SELECT * FROM listings 
WHERE (publishedon BETWEEN 1441105258 AND 1443614458) 
  AND (published = 1) 
  AND (cat_id in(1,5)) 
ORDER BY views DESC

这是解释

这个查询太慢了,因为ORDER BY的意见是DESC

那么我试图删除旧的索引并添加它

CREATE INDEX `listings_pcs` ON listings(
    `publishedon` DESC,`source_id`,`views` DESC
)

它也太慢了

如果我在发行版上只使用单个索引呢?
在cat_id,source_id,views,publishedon上使用单个索引呢?

如果我发现其他索引方法取决于任何其他列,我可以在一个月内更改发布的查询依赖关系

如何在(cat_id,publishedon,published)中创建索引?但在某些情况下,我将仅使用source_id?

X- 20045 X- 200 X- 200 200 X- 200 200:

关于为什么您的查询没有得到更快的一个重要的通用注意事项,尽管您尝试的是索引目前不支持MysqL上的DESC.看到这个 SO thread和 the source.

在这种情况下,您最大的问题是您的记录的大小.如果引擎决定使用索引不会更快,那么它不会.

你有几个选择,所有的都是相当不错的,可以帮助你看到显着的改进.

关于sql的注释

首先,我想对sql中的索引进行快速注释.虽然我不认为这是您的困境的解决方案,但这是您的主要问题,可以帮助您.

它通常可以帮助我在三个不同的桶中考虑索引.绝对的,也许,永远不会.你的索引当然没有任何东西在从未列,但有一些我会考虑“可能”的索引.

绝对:这是你的主键和任何外键.您也可以定期参考从您拥有的大量数据中提取一小组数据的任何键.

也许:这些列,虽然你可以定期引用它们,但它们本身并没有被真正引用.事实上,通过分析和使用EXPLAIN作为@Machavity在他的答案中推荐,你可能会发现,在这些列用于删除字段之前,没有那么多字段.对于我来说,这个专栏的一个例子就是公布的专栏.请记住,每个INDEX都会添加您的查询所需的工作.

另外:当您经常搜索基于两个不同列的数据时,复合键是一个不错的选择.稍后再说.

选项,选项,选项…

有很多选择要考虑,每个都有一些缺点.最终我会逐案考虑这些,因为我没有看到这些是一个银弹.理想情况下,您将根据当前设置测试一些不同的解决方案,并使用一个很好的科学测试来查看哪个解决方案最快.

>将sql表拆分成两个或多个单独的表.

这是少数几个之一,尽管表中的列数,我不会急于尝试将您的表分成更小的块.但是,如果您决定将其拆分成较小的块,我会认为您可以轻松地将[action] edon,[action] edby_id和[action]

+-----------+-------------+------+-----+-------------------+----------------+
| Field     | Type        | Null | Key | Default           | Extra          |
+-----------+-------------+------+-----+-------------------+----------------+
| id        | int(11)     | NO   | PRI | NULL              | auto_increment |
| action_id | int(11)     | NO   |     | NULL              |                |
| action    | varchar(45) | NO   |     | NULL              |                |
| date      | datetime    | NO   |     | CURRENT_TIMESTAMP |                |
| user_id   | int(11)     | NO   |     | NULL              |                |
+-----------+-------------+------+-----+-------------------+----------------+

缺点是它不允许您确保只有一个创建日期没有TRIGGER.有利的是,当您按日期排序时,您无需排列具有尽可能多的索引的列数.此外,它允许您排序不仅可以创建,而且还可以通过所有其他操作进行排序.

编辑:根据请求,这里是一个抽样排序查询

SELECT * FROM listings 
INNER JOIN actions ON actions.listing_id = listings.id
WHERE (actions.action = 'published') 
  AND (listings.published = 1) 
  AND (listings.cat_id in(1,5)) 
  AND (listings.source_id  in(1,5)) 
  AND (actions.actiondate between 1441105258 AND 1443614458)
ORDER BY listings.views DESC

理论上,它应该减少你排序的行数,因为它只是拉取相关数据.我没有像你的数据集,所以我现在不能测试!

如果您将复合键放在actiondate和listing.id上,这应该有助于提高速度.

正如我所说,我不认为这是你现在最好的解决方案,因为我不相信它会给你最大的优化.这导致我的下一个建议:

>创建一个月字段

我使用this nifty tool来确认我以为我理解你的问题:你在这里按月排序.您的示例特别在9月1日至9月30日期间.

因此,另一个选项是将您的整数函数拆分为月,日,年字段.您仍然可以拥有您的时间戳,但时间戳并不适合搜索.运行一个EXPLAIN甚至一个简单的查询,你会看到自己.

这样,您可以索引月份和年份字段,并进行如下查询:

SELECT * FROM listings 
WHERE (publishedmonth = 9)
  AND (publishedyear = 2015) 
  AND (published = 1) 
  AND (cat_id in(1,5)) 
ORDER BY views DESC

在前面拍一个EXPLAIN,你应该看到很大的改进.

因为您计划参考一个月和一天,您可能需要针对月和年添加复合键,而不是单独添加一个复合键,以增加增益.

注意:我想清楚,这不是“正确”的做事方式.方便,但非规范化.如果你想要正确的方法来做事情,你会适应像this link这样的一些事情,但是我认为这将需要你认真地重新考虑你的桌子,而且我没有这样做,没有必要,坦率地说,将会,刷上我的几何.我认为这是一个有点过分的你想做什么.

>在别的地方做你的重排序

这对我来说很难,因为我喜欢尽可能地做“sql”的方式,但这并不总是最好的解决方案.例如,重型计算最好使用您的编程语言,让sql处理关系.

Digg的前CTO使用PHP而不是MysqL进行排序,并获得了4,000% performance increase.当然,您可能不会扩展到此级别,因此除非您自己测试,否则性能权衡将不会被清除.然而,这个概念是健全的:数据库是瓶颈,电脑内存比较便宜.

无疑可以做更多的调整.这些都有一个缺点,需要一些投资.最好的答案是测试两个或更多的这些,看看哪一个可以帮助你获得最大的改进.

php – MySQL索引 – 根据此表和查询的最佳做法是什么?的更多相关文章

  1. 从iOS应用程序发送帖子到PHP脚本不工作…简单的解决方案就像

    我之前已经做了好几次了但是由于某些原因我无法通过这个帖子…我尝试了设置为_POST且没有的变量的PHP脚本……当它们未设置为发布时它工作精细.这是我的iOS代码:这里是PHP的一大块,POST变量不在正确的位置?我想这对于更有经验的开发人员来说是一个相当简单的答案,感谢您的帮助!解决方法$_POST是一个数组,而不是一个函数.您需要使用方括号来访问数组索引:

  2. swift学习2 元组 tuples

    swift中出现了一种新的数据结构,非常牛掰的元组tuples如果懂PHP的猿,会发现这个元组和PHP的数组非常类似,同样是可以默认不指定key,也可以指定key目前的学习疑问是,如何进行元组的遍历?

  3. 尝试使用swift mailer,gmail smtp,php发送邮件

    这里是我的代码:在运行时出现此错误…

  4. Android – 将SQLite与MySQL同步的最佳方式

    参见英文答案>Synchronizingclient-serverdatabases5个我正在开发一个包含网络应用和移动应用程序的项目,该应用程序记录每日用户的数据.用户可以删除,更新他们的数据,他们可以使用许多设备插入数据.我打算这样开发:用户输入他们的数据然后插入sqlite.服务将定期启动(每5小时或每小时)以使用时间戳与MysqL同步.我确实在互联网上使用服务和时间戳搜索了一个样本,但我一

  5. android – 如何将唯一的GCM注册标识存储到MySQL中

    我正在设置GoogleCloudMessaging机制的服务器端,使用MySQL存储移动应用提供的注册ID.Google可以发出最多4k个注册码,我被迫将其存储在TEXT字段中.所有的好,到目前为止,问题是我必须处理这样的情况:>用户登录到应用程序>该应用从google请求注册ID>应用程序将新的注册ID发送到应用服务器>服务器存储该注册ID并将其链接到当前登录的用户>该用户注销并且新用户登录>应

  6. PHP使用JpGraph绘制折线图操作示例【附源码下载】

    这篇文章主要介绍了PHP使用JpGraph绘制折线图操作,结合实例形式分析了php使用JpGraph的相关操作技巧与注意事项,并附带源码供读者下载参考,需要的朋友可以参考下

  7. jQuery的Cookie封装,与PHP交互的简单实现

    下面小编就为大家带来一篇jQuery的Cookie封装,与PHP交互的简单实现。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  8. PHP+jquery+CSS制作头像登录窗(仿QQ登陆)

    本篇文章介绍了PHP结合jQ和CSS制作头像登录窗(仿QQ登陆),实现了类似QQ的登陆界面,很有参考价值,有需要的朋友可以了解一下。

  9. 如何在PHP环境中使用ProtoBuf数据格式

    这篇文章主要介绍了如何在PHP环境中使用ProtoBuf数据格式,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

  10. PHP rsa加密解密算法原理解析

    这篇文章主要介绍了PHP rsa加密解密算法原理解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

随机推荐

  1. PHP个人网站架设连环讲(一)

    先下一个OmnihttpdProffesinalV2.06,装上就有PHP4beta3可以用了。PHP4给我们带来一个简单的方法,就是使用SESSION(会话)级变量。但是如果不是PHP4又该怎么办?我们可以假设某人在15分钟以内对你的网页的请求都不属于一个新的人次,这样你可以做个计数的过程存在INC里,在每一个页面引用,访客第一次进入时将访问时间送到cookie里。以后每个页面被访问时都检查cookie上次访问时间值。

  2. PHP函数学习之PHP函数点评

    PHP函数使用说明,应用举例,精简点评,希望对您学习php有所帮助

  3. ecshop2.7.3 在php5.4下的各种错误问题处理

    将方法内的函数,分拆为2个部分。这个和gd库没有一点关系,是ecshop程序的问题。会出现这种问题,不外乎就是当前会员的session或者程序对cookie的处理存在漏洞。进过本地测试,includes\modules\integrates\ecshop.php这个整合自身会员的类中没有重写integrate.php中的check_cookie()方法导致,验证cookie时返回的username为空,丢失了登录状态,在ecshop.php中重写了此方法就可以了。把他加到ecshop.php的最后面去就可

  4. NT IIS下用ODBC连接数据库

    $connection=intodbc_connect建立数据库连接,$query_string="查询记录的条件"如:$query_string="select*fromtable"用$cur=intodbc_exec检索数据库,将记录集放入$cur变量中。再用while{$var1=odbc_result;$var2=odbc_result;...}读取odbc_exec()返回的数据集$cur。最后是odbc_close关闭数据库的连接。odbc_result()函数是取当前记录的指定字段值。

  5. PHP使用JpGraph绘制折线图操作示例【附源码下载】

    这篇文章主要介绍了PHP使用JpGraph绘制折线图操作,结合实例形式分析了php使用JpGraph的相关操作技巧与注意事项,并附带源码供读者下载参考,需要的朋友可以参考下

  6. zen_cart实现支付前生成订单的方法

    这篇文章主要介绍了zen_cart实现支付前生成订单的方法,结合实例形式详细分析了zen_cart支付前生成订单的具体步骤与相关实现技巧,需要的朋友可以参考下

  7. Thinkphp5框架实现获取数据库数据到视图的方法

    这篇文章主要介绍了Thinkphp5框架实现获取数据库数据到视图的方法,涉及thinkPHP5数据库配置、读取、模型操作及视图调用相关操作技巧,需要的朋友可以参考下

  8. PHP+jquery+CSS制作头像登录窗(仿QQ登陆)

    本篇文章介绍了PHP结合jQ和CSS制作头像登录窗(仿QQ登陆),实现了类似QQ的登陆界面,很有参考价值,有需要的朋友可以了解一下。

  9. 基于win2003虚拟机中apache服务器的访问

    下面小编就为大家带来一篇基于win2003虚拟机中apache服务器的访问。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  10. Yii2中组件的注册与创建方法

    这篇文章主要介绍了Yii2之组件的注册与创建的实现方法,非常不错,具有参考借鉴价值,需要的朋友可以参考下

返回
顶部