我正在尝试优化一个简单的 sql 查询,该查询将多次运行大量数据。
这是场景:
一个真正的查询:
SELECT one_field, another_field
FROM big_table
INNER JOIN medium_table ON ( ... )
INNER JOIN small_table ON ( ... )
WHERE week >= #number AND week <= #number AND year >= #number AND year <= #number
AND medium_table.indexed_field = #number
AND small_table.pk= #number
部分测试结果:
如何改进查询或数据库方案?
最好将我的年/周字段连接到 [yearweek] 索引字段中?
在一些基准测试中,我发现 MyISAM 比 Innodb 快,但似乎我有一点改进:
http://www.mysqlperformanceblog.com/files/benchmarks/innodb-myisam-falcon.html
http://www.jortk.nl/2008/12/mysql-performance-benchmark-myisam-versus-innodb/
丢掉 FK 去 MyISAM 值得吗?
谢谢!
更新:
选择说明:
1 SIMPLE small_table const PRIMARY PRIMARY 4 const 1 Using index
1 SIMPLE medium_table index_merge PRIMARY,Fk_small_table, Fk_indexed_field Fk_small_table, Fk_indexed_field 5,5 250 Using intersect(Fk_small_table, Fk_indexed_field); Using where
1 SIMPLE big_table ref Fk_code_of_medium_table,week-year-compound-index Fk_three 5 medium_table.primary_key 4 Using where
数据库模式:
CREATE TABLE IF NOT EXISTS `db`.`big_table` (
`primary_key` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT ,
`code_of_medium_table` INT UNSIGNED NULL ,
`week` SMALLINT UNSIGNED NULL ,
`year` YEAR NULL ,
......
PRIMARY KEY (`primary_key`) ,
INDEX `Fk_code_of_medium_table` (`code_of_medium_table` ASC) ,
INDEX `In_week-year` (`week` ASC, `year` ASC) ,
CONSTRAINT `Fk_code_of_medium_table`
FOREIGN KEY (`code_of_medium_table` )
REFERENCES `db`.`medium_table` (`code` )
ON DELETE NO ACTION
ON UPDATE NO ACTION,
ENGINE = InnoDB
CREATE TABLE IF NOT EXISTS `db`.`medium_table` (
`primary_key` INT UNSIGNED NOT NULL AUTO_INCREMENT ,
.....
`code_of_small_table` INT UNSIGNED NULL ,
`indexed_field ` INT UNSIGNED NULL ,
PRIMARY KEY (`primary_key`) ,
INDEX `Fk_code_of_small_table` (`code_of_small_table` ASC) ,
INDEX `Fk_indexed_field` (`another_field` ASC) ,
CONSTRAINT `Fk_code_of_small_table`
FOREIGN KEY (`code_of_small_table` )
REFERENCES `db`.`small_table` (`code` )
ON DELETE NO ACTION
ON UPDATE NO ACTION,
CONSTRAINT `Fk_indexed_field `
FOREIGN KEY (`indexed_field ` )
REFERENCES `db`.`other_table` (`code` )
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB
CREATE TABLE IF NOT EXISTS `db`.`small_table` (
`primary_key` INT UNSIGNED NOT NULL AUTO_INCREMENT ,
.....
PRIMARY KEY (`primary_key`) )
ENGINE = InnoDB
变量输出:
auto_increment_increment 1
auto_increment_offset 1
automatic_sp_privileges ON
back_log 50
basedir /usr/
bdb_cache_size 8384512
bdb_home /var/lib/mysql/
bdb_log_buffer_size 262144
bdb_logdir
bdb_max_lock 10000
bdb_shared_data OFF
bdb_tmpdir /tmp/
binlog_cache_size 32768
bulk_insert_buffer_size 8388608
character_set_client utf8
character_set_connection utf8
character_set_database latin1
character_set_filesystem binary
character_set_results utf8
character_set_server latin1
character_set_system utf8
character_sets_dir /usr/share/mysql/charsets/
collation_connection utf8_general_ci
collation_database latin1_swedish_ci
collation_server latin1_swedish_ci
completion_type 0
concurrent_insert 1
connect_timeout 10
datadir /var/lib/mysql/
date_format %Y-%m-%d
datetime_format %Y-%m-%d %H:%i:%s
default_week_format 0
delay_key_write ON
delayed_insert_limit 100
delayed_insert_timeout 300
delayed_queue_size 1000
div_precision_increment 4
keep_files_on_create OFF
engine_condition_pushdown OFF
expire_logs_days 0
flush OFF
flush_time 0
ft_boolean_syntax + -><()~*:""&|
ft_max_word_len 84
ft_min_word_len 4
ft_query_expansion_limit 20
ft_stopword_file (built-in)
group_concat_max_len 1024
have_archive NO
have_bdb YES
have_blackhole_engine NO
have_compress YES
have_crypt YES
have_csv NO
have_dynamic_loading YES
have_example_engine NO
have_federated_engine NO
have_geometry YES
have_innodb YES
have_isam NO
have_merge_engine YES
have_ndbcluster NO
have_openssl DISABLED
have_ssl DISABLED
have_query_cache YES
have_raid NO
have_rtree_keys YES
have_symlink YES
hostname EarnedBE002
init_connect
init_file
init_slave
innodb_additional_mem_pool_size 1048576
innodb_autoextend_increment 8
innodb_buffer_pool_awe_mem_mb 0
innodb_buffer_pool_size 8388608
innodb_checksums ON
innodb_commit_concurrency 0
innodb_concurrency_tickets 500
innodb_data_file_path ibdata1:10M:autoextend
innodb_data_home_dir
innodb_adaptive_hash_index ON
innodb_doublewrite ON
innodb_fast_shutdown 1
innodb_file_io_threads 4
innodb_file_per_table OFF
innodb_flush_log_at_trx_commit 1
innodb_flush_method
innodb_force_recovery 0
innodb_lock_wait_timeout 50
innodb_locks_unsafe_for_binlog OFF
innodb_log_arch_dir
innodb_log_archive OFF
innodb_log_buffer_size 1048576
innodb_log_file_size 5242880
innodb_log_files_in_group 2
innodb_log_group_home_dir ./
innodb_max_dirty_pages_pct 90
innodb_max_purge_lag 0
innodb_mirrored_log_groups 1
innodb_open_files 300
innodb_rollback_on_timeout OFF
innodb_support_xa ON
innodb_sync_spin_loops 20
innodb_table_locks ON
innodb_thread_concurrency 8
innodb_thread_sleep_delay 10000
interactive_timeout 28800
join_buffer_size 131072
key_buffer_size 8384512
key_cache_age_threshold 300
key_cache_block_size 1024
key_cache_division_limit 100
language /usr/share/mysql/english/
large_files_support ON
large_page_size 0
large_pages OFF
lc_time_names en_US
license GPL
local_infile ON
locked_in_memory OFF
log OFF
log_bin OFF
log_bin_trust_function_creators OFF
log_error
log_queries_not_using_indexes OFF
log_slave_updates OFF
log_slow_queries OFF
log_warnings 1
long_query_time 10
low_priority_updates OFF
lower_case_file_system OFF
lower_case_table_names 0
max_allowed_packet 1048576
max_binlog_cache_size 18446744073709547520
max_binlog_size 1073741824
max_connect_errors 10
max_connections 100
max_delayed_threads 20
max_error_count 64
max_heap_table_size 16777216
max_insert_delayed_threads 20
max_join_size 18446744073709551615
max_length_for_sort_data 1024
max_prepared_stmt_count 16382
max_relay_log_size 0
max_seeks_for_key 18446744073709551615
max_sort_length 1024
max_sp_recursion_depth 0
max_tmp_tables 32
max_user_connections 0
max_write_lock_count 18446744073709551615
multi_range_count 256
myisam_data_pointer_size 6
myisam_max_sort_file_size 9223372036853727232
myisam_recover_options OFF
myisam_repair_threads 1
myisam_sort_buffer_size 8388608
myisam_stats_method nulls_unequal
net_buffer_length 16384
net_read_timeout 30
net_retry_count 10
net_write_timeout 60
new OFF
old_passwords OFF
open_files_limit 1024
optimizer_prune_level 1
optimizer_search_depth 62
pid_file /var/run/mysqld/mysqld.pid
plugin_dir
port 3306
preload_buffer_size 32768
profiling OFF
profiling_history_size 15
protocol_version 10
query_alloc_block_size 8192
query_cache_limit 1048576
query_cache_min_res_unit 4096
query_cache_size 0
query_cache_type ON
query_cache_wlock_invalidate OFF
query_prealloc_size 8192
range_alloc_block_size 4096
read_buffer_size 131072
read_only OFF
read_rnd_buffer_size 262144
relay_log
relay_log_index
relay_log_info_file relay-log.info
relay_log_purge ON
relay_log_space_limit 0
rpl_recovery_rank 0
secure_auth OFF
secure_file_priv
server_id 0
skip_external_locking ON
skip_networking OFF
skip_show_database OFF
slave_compressed_protocol OFF
slave_load_tmpdir /tmp/
slave_net_timeout 3600
slave_skip_errors OFF
slave_transaction_retries 10
slow_launch_time 2
socket /var/lib/mysql/mysql.sock
sort_buffer_size 2097144
sql_big_selects ON
sql_mode
sql_notes ON
sql_warnings OFF
ssl_ca
ssl_capath
ssl_cert
ssl_cipher
ssl_key
storage_engine MyISAM
sync_binlog 0
sync_frm ON
system_time_zone UTC
table_cache 64
table_lock_wait_timeout 50
table_type MyISAM
thread_cache_size 0
thread_stack 262144
time_format %H:%i:%s
time_zone SYSTEM
timed_mutexes OFF
tmp_table_size 33554432
tmpdir /tmp/
transaction_alloc_block_size 8192
transaction_prealloc_size 4096
tx_isolation REPEATABLE-READ
updatable_views_with_limit YES
version 5.0.77
version_bdb Sleepycat Software: Berkeley DB 4.1.24: (January 29, 2009)
version_comment Source distribution
version_compile_machine x86_64
version_compile_os redhat-linux-gnu
wait_timeout 28800
使用 ypercube 提出的索引,目前,这是最快的查询(平均 2,107 秒):
SELECT SQL_NO_CACHE int_field, varchar_field
FROM big_table
INNER JOIN medium_table ON ( ... )
INNER JOIN small_table ON ( ... )
WHERE week BETWEEN #number AND #number
AND year BETWEEN #number AND #number
AND small_table.pk = 248
AND medium_table.indexed_field = #number
最佳答案
我希望您能找到我感兴趣的以下链接和以前的答案。
我希望我能为您的问题提供一个具体的答案,但我没有时间完全了解您的架构:命名约定太糟糕了,缺乏有用的信息,不一致等等......
但是,您应该在下面找到问题的解决方案,这与切换到性能较低的 myisam 引擎无关!
以下答案之一的片段:
You should read the following and learn a little bit about the advantages of a well designed innodb table and how best to use clustered indexes - only available with innodb !
聚集索引:
http://dev.mysql.com/doc/refman/5.0/en/innodb-index-types.html
http://www.xaprb.com/blog/2006/07/04/how-to-exploit-mysql-index-optimizations/
我以前的回答:
60 million entries, select entries from a certain month. How to optimize database?
MySQL and NoSQL: Help me to choose the right one
How to avoid "Using temporary" in many-to-many queries?
Optimal MySQL settings for queries that deliver large amounts of data?
希望这有帮助:)
关于MySQL InnoDB 查询性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6174246/
我正在用Ruby编写一个简单的程序来检查域列表是否被占用。基本上它循环遍历列表,并使用以下函数进行检查。require'rubygems'require'whois'defcheck_domain(domain)c=Whois::Client.newc.query("google.com").available?end程序不断出错(即使我在google.com中进行硬编码),并打印以下消息。鉴于该程序非常简单,我已经没有什么想法了-有什么建议吗?/Library/Ruby/Gems/1.8/gems/whois-2.0.2/lib/whois/server/adapters/base.
我知道我可以指定某些字段来使用pluck查询数据库。ids=Item.where('due_at但是我想知道,是否有一种方法可以指定我想避免从数据库查询的某些字段。某种反拔?posts=Post.where(published:true).do_not_lookup(:enormous_field) 最佳答案 Model#attribute_names应该返回列/属性数组。您可以排除其中一些并传递给pluck或select方法。像这样:posts=Post.where(published:true).select(Post.attr
我正在尝试查询我的Rails数据库(Postgres)中的购买表,我想查询时间范围。例如,我想知道在所有日期的下午2点到3点之间进行了多少次购买。此表中有一个created_at列,但我不知道如何在不搜索特定日期的情况下完成此操作。我试过:Purchases.where("created_atBETWEEN?and?",Time.now-1.hour,Time.now)但这最终只会搜索今天与那些时间的日期。 最佳答案 您需要使用PostgreSQL'sdate_part/extractfunction从created_at中提取小时
我正在使用Ruby解决一些ProjectEuler问题,特别是这里我要讨论的问题25(Fibonacci数列中包含1000位数字的第一项的索引是多少?)。起初,我使用的是Ruby2.2.3,我将问题编码为:number=3a=1b=2whileb.to_s.length但后来我发现2.4.2版本有一个名为digits的方法,这正是我需要的。我转换为代码:whileb.digits.length当我比较这两种方法时,digits慢得多。时间./025/problem025.rb0.13s用户0.02s系统80%cpu0.190总计./025/problem025.rb2.19s用户0.0
我在Rails上使用带有ruby的solr。一切正常,我只需要知道是否有任何现有代码来清理用户输入,比如以?开头的查询。或* 最佳答案 我不知道执行此操作的任何代码,但理论上可以通过查看parsingcodeinLucene来完成并搜索thrownewParseException(只有16个匹配!)。在实践中,我认为您最好只捕获代码中的任何solr异常并显示“无效查询”消息或类似信息。编辑:这里有几个“sanitizer”:http://pivotallabs.com/users/zach/blog/articles/937-s
我正在寻找一个用ruby演示计时器的在线示例,并发现了下面的代码。它按预期工作,但这个简单的程序使用30Mo内存(如Windows任务管理器中所示)和太多CPU有意义吗?非常感谢deftime_blockstart_time=Time.nowThread.new{yield}Time.now-start_timeenddefrepeat_every(seconds)whiletruedotime_spent=time_block{yield}#Tohandle-vesleepinteravalsleep(seconds-time_spent)iftime_spent
我正在为锦标赛开发一个Rails应用程序。我在这个查询中使用了三个模型:classPlayertruehas_and_belongs_to_many:tournamentsclassTournament:destroyclassPlayerMatch"Player",:foreign_key=>"player_one"belongs_to:player_two,:class_name=>"Player",:foreign_key=>"player_two"在tournaments_controller的显示操作中,我调用以下查询:Tournament.where(:id=>params
我想用sunspot重现以下原始solr查询q=exact_term_text:fooORterm_textv:foo*ORalternate_text:bar*但我无法通过标准的太阳黑子界面理解这是否可能以及如何实现,因为看起来:fulltext方法似乎不接受多个文本/搜索字段参数我不知道将什么参数作为第一个参数传递给fulltext,就好像我通过了"foo"或"bar"结果不匹配如果我传递一个空参数,我得到一个q=*:*范围过滤器(例如with(:term).starting_with('foo*')(顾名思义)作为过滤器查询应用,因此不参与评分。似乎可以手动编写字符串(或者可能使
如果用户是所有者,我有一个条件来检查说删除和文章。delete_articleifuser.owner?另一种方式是user.owner?&&delete_article选择它有什么好处还是它只是一种写作风格 最佳答案 性能不太可能成为该声明的问题。第一个要好得多-它更容易阅读。您future的自己和其他将开始编写代码的人会为此感谢您。 关于ruby-on-rails-如果条件与&&,是否有任何性能提升,我们在StackOverflow上找到一个类似的问题:
例如,假设我有一个名为Products的模型,并且在ProductsController中,我有以下代码用于product_listView以显示已排序的产品。@products=Product.order(params[:order_by])让我们想象一下,在product_listView中,用户可以使用下拉菜单按价格、评级、重量等进行排序。数据库中的产品不会经常更改。我很难理解的是,每次用户选择新的order_by过滤器时,rails是否必须查询,或者rails是否能够以某种方式缓存事件记录以在服务器端重新排序?有没有一种方法可以编写它,以便在用户排序时rails不会重新查询结果