sql >> データベース >  >> RDS >> Mysql

MySQLの隠された機能

    あなたが賞金をあげたので、私は苦労して獲得した秘密を共有します...

    一般に、今日私が調整したすべてのSQLは、サブクエリを使用する必要がありました。 Oracleデータベースの世界から来たので、私が当然と思っていたものは、MySQLと同じようには機能しませんでした。そして、MySQLのチューニングについて読んだことで、クエリの最適化に関してMySQLはOracleに遅れをとっていると結論付けることができます。

    ほとんどのB2Cアプリケーションに必要な単純なクエリはMySQLでうまく機能する可能性がありますが、インテリジェンスレポートに必要な集約レポートタイプのクエリのほとんどは、MySQLがそれらをより高速に実行できるようにSQLクエリをかなり計画および再編成する必要があるようです。

    管理:

    max_connections 同時接続の数です。デフォルト値は100接続(5.0以降は151)です-非常に小さいです。

    注:

    接続にはメモリが必要であり、OSが多くの接続を処理できない場合があります。

    Linux / x86用のMySQLバイナリでは、最大4096の同時接続が可能ですが、自己コンパイルされたバイナリには、多くの場合、制限が少なくなっています。

    開いているテーブルと同時接続の数に一致するようにtable_cacheを設定します。 open_tablesの値を確認してください。値が急速に大きくなっている場合は、サイズを大きくする必要があります。

    注:

    前の2つのパラメーターでは、多くの開いているファイルが必要になる場合があります。 20 + max_connections + table_cache * 2は、必要なものの適切な見積もりです。 Linux上のMySQLにはopen_file_limitオプションがあり、この制限を設定します。

    複雑なクエリがある場合は、sort_buffer_sizeとtmp_table_sizeが非常に重要になる可能性があります。値はクエリの複雑さと利用可能なリソースによって異なりますが、それぞれ4Mbと32Mbが開始点として推奨されます。

    注:これらは、read_buffer_size、read_rnd_buffer_sizeなどの「接続ごとの」値であり、接続ごとにこの値が必要になる可能性があることを意味します。したがって、これらのパラメータを設定するときは、負荷と使用可能なリソースを考慮してください。たとえば、sort_buffer_sizeは、MySQLがソートを実行する必要がある場合にのみ割り当てられます。注:メモリが不足しないように注意してください。

    多くの接続が確立されている場合(つまり、永続的な接続がないWebサイト)、thread_cache_sizeをゼロ以外の値に設定することでパフォーマンスを向上させることができます。 16は最初から良い値です。 thread_createdがあまり速く成長しなくなるまで、値を増やします。

    主キー:

    テーブルごとに存在できるAUTO_INCREMENT列は1つだけであり、インデックスを付ける必要があり、DEFAULT値を持つことはできません

    KEYは通常、INDEXの同義語です。キー属性PRIMARYKEYは、列定義で指定された場合、単にKEYとして指定することもできます。これは、他のデータベースシステムとの互換性のために実装されました。

    PRIMARY KEYは、すべてのキー列をNOTNULLとして定義する必要がある一意のインデックスです

    PRIMARY KEYまたはUNIQUEインデックスが、整数型の1つの列のみで構成されている場合は、SELECTステートメントでその列を「_rowid」と呼ぶこともできます。

    MySQLでは、PRIMARYKEYの名前はPRIMARY

    です。

    現在、外部キーをサポートしているのはInnoDB(v5.1?)テーブルのみです。

    通常、テーブルを作成するときに必要なすべてのインデックスを作成します。PRIMARYKEY、KEY、UNIQUE、またはINDEXとして宣言された列にはインデックスが付けられます。

    NULLは、「値がない」ことを意味します。 NULLをテストするには、できません =、<、<>などの算術比較演算子を使用します。代わりに、ISNULLおよびISNOT NULL演算子を使用してください:

    NO_AUTO_VALUE_ON_ZEROは、0の自動インクリメントを抑制して、NULLのみが次のシーケンス番号を生成するようにします。このモードは、テーブルのAUTO_INCREMENT列に0が格納されている場合に役立ちます。 (ちなみに、0を保存することはお勧めできません。)

    新しい行に使用されるAUTO_INCREMENTカウンターの値を変更するには:

    ALTER TABLE mytable AUTO_INCREMENT = value; 
    

    orSET INSERT_ID =value;

    特に指定がない限り、値は1000000で始まるか、次のように指定します:

    ...)ENGINE =MyISAM DEFAULT CHARSET =latin1 AUTO_INCREMENT =1

    タイムスタンプ:

    TIMESTAMP列の値は、保存のために現在のタイムゾーンからUTCに変換され、取得のためにUTCから現在のタイムゾーンに変換されます。

    http://dev.mysql.com/doc/refman/5.1 /en/timestamp.html テーブル内の1つのTIMESTAMP列に対して、現在のタイムスタンプをデフォルト値および自動更新値として割り当てることができます。

    WHERE句でこれらのタイプのいずれかを使用する場合に注意する必要があるのは、WHERE datecolumn =FROM_UNIXTIME(1057941242)であり、WHERE UNIX_TIMESTAMP(datecolumn)=1057941242ではないことです。後者を実行しても、そのインデックスは利用されません。列。

    http://dev.mysql.com /doc/refman/5.1/en/date-and-time-functions.html

     UNIX_TIMESTAMP() 
     FROM_UNIXTIME() 
     UTC_DATE()
     UTC_TIME()
     UTC_TIMESTAMP()
    

    MySQLで日時をUNIXタイムスタンプに変換する場合:
    次に24時間を追加します:
    次にそれを日時に戻すと魔法のように1時間が失われます!

    これが何が起こっているかです。 UNIXタイムスタンプを日時に戻す場合、タイムゾーンが考慮されます。2006年10月28日から29日の間に、夏時間がなくなり、1時間が失われました。

    MySQL 4.1.3以降、CURRENT_TIMESTAMP()、CURRENT_TIME()、CURRENT_DATE()、およびFROM_UNIXTIME()関数は、接続の現在のタイムゾーンの値を返します。 、time_zoneシステム変数の値として使用できます。さらに、UNIX_TIMESTAMP()は、その引数が現在のタイムゾーンの日時値であると想定しています。

    現在のタイムゾーン設定は、UTC_TIMESTAMP()などの関数によって表示される値、またはDATE、TIME、またはDATETIME列の値には影響しません。

    注:更新時のみ フィールドが変更された場合にDateTimeを更新しますUPDATEによってフィールドが変更されない場合、DateTimeは更新されません!

    さらに、最初のTIMESTAMPは、指定されていない場合でも、デフォルトで常にAUTOUPDATEです

    日付を使用する場合、ほとんどの場合、データの計算は整数の加算または減算の単純な問題であり、同じ理由で真夜中からの秒数であるため、ユリウス日を熟考します。秒よりも細かい粒度の時間の再調整が必要になることはめったにありません。

    これらは両方とも4バイト整数として格納でき、スペースが非常に狭い場合は、UNIX時間(エポック1/1/1970からの秒数)に符号なし整数として組み合わせることができます。これは、2106年頃まで次のようになります。

    >

    '24時間の秒数=86400

    '符号付き整数maxval=2,147,483,647-68年の秒を保持できます

    'unsigned Integer max val=4,294,967,295-136年の秒数を保持できます

    バイナリプロトコル:

    MySQL 4.1では、文字列以外のデータ値を文字列形式との間で変換せずにネイティブ形式で送信および返すことができるバイナリプロトコルが導入されました。 (非常に便利です)

    余談ですが、mysql_real_query()は、ステートメント文字列を操作するためにstrlen()を呼び出さないため、mysql_query()よりも高速です。

    http://dev.mysql.com/tech-resources /articles/4.1/prepared-statements.html バイナリプロトコルは、サーバー側のプリペアドステートメントをサポートし、ネイティブ形式でのデータ値の送信を可能にします。バイナリプロトコルは、MySQL4.1の以前のリリースでかなりの改訂が行われました。

    IS_NUM()マクロを使用して、フィールドに数値タイプがあるかどうかをテストできます。タイプ値をIS_NUM()に渡すと、フィールドが数値の場合はTRUEと評価されます。

    注意すべき点の1つは、バイナリデータが CANであるということです。 エスケープしてMySQLに必要なのはのみであることを覚えている場合は、通常のクエリ内に送信されます そのバックスラッシュと引用文字はエスケープされます。これは、たとえば暗号化/塩漬けパスワードなどの短いバイナリ文字列を挿入するための非常に簡単な方法です。

    マスターサーバー:

    http://www.experts-exchange.com/Database/MySQL/Q_22967482 .html

    http://www.databasejournal.com/features/mysql/article.php / 10897_3355201_2

    にレプリケーションスレーブを付与します。 'slave_password'によって識別されるslave_userへ

    #Master Binary Logging Config  STATEMENT causes replication 
                  to be statement-based -  default
    
    log-bin=Mike
    binlog-format=STATEMENT
    server-id=1            
    max_binlog_size = 10M
    expire_logs_days = 120    
    
    
    #Slave Config
    master-host=master-hostname
    master-user=slave-user
    master-password=slave-password
    server-id=2
    

    バイナリログファイルは次のように読み取る必要があります:

    http://dev.mysql.com/doc/refman /5.0/en/binary-log.html

    http://www.mydigitallife.info/2007/10/06/how-to-read-mysql-binary-log-files-binlog-with-mysqlbinlog/

    http://dev.mysql.com/doc/refman/5.1 /en/mysqlbinlog.html

    http://dev.mysql.com/doc/refman /5.0/en/binary-log.html

    http://dev.mysql.com/doc /refman/5.1/en/binary-log-setting.html

    RESET MASTERステートメントを使用してすべてのバイナリログファイルを削除するか、PURGEMASTERを使用してそれらのサブセットを削除できます

    --result-file =binlog.txt TrustedFriend-bin.000030

    正規化:

    http://dev.mysql.com/tech-resources /articles/intro-to-normalization.html

    UDF機能

    http://www.koders.com/cpp/fid10666379322B54AD41AEB0E4100D87C8CD

    http://souptonuts.sourceforge.net/readme_mysql.htm

    データ型:

    http://dev.mysql.com/doc/refman /5.1/en/storage-requirements.html

    http://www.informit.com/articles/article.aspx ?p =1238838&seqNum =2

    http://bitfilm。 net / 2008/03/24 / Saving-bytes-efficient-data-storage-mysql-part-1 /

    注意すべき点の1つは、CHARとVARCHARの両方を含む混合テーブルでは、mySQLがCHARをVARCHARに変更することです

    RecNum integer_type UNSIGNED NOT NULL AUTO_INCREMENT、PRIMARY KEY(RecNum)

    MySQLは、標準のSQLおよびISO 8601仕様に従って、常に最初の年で日付を表します

    その他:

    一部のMySQl機能をオフにすると、データファイルが小さくなり、アクセスが高速になります。例:

    --datadirはデータディレクトリと

    を指定します

    --skip-innodbはinnoオプションをオフにし、10〜20M節約します

    詳細はこちら http://dev.mysql.com/tech -resources / articles / mysql-c-api.html

    第7章をダウンロード-無料

    InnoDBはトランザクションですが、それに伴うパフォーマンスのオーバーヘッドがあります。 MyISAMテーブルは私のプロジェクトの90%に十分であることがわかりました。非トランザクションセーフテーブル(MyISAM)には、それ自体にいくつかの利点があります。これらはすべて、次の理由で発生します。

    トランザクションのオーバーヘッドはありません:

    はるかに高速

    より低いディスクスペース要件

    更新を実行するために必要なメモリが少ない

    各MyISAMテーブルは、ディスクに3つのファイルで保存されます。ファイルの名前はテーブル名で始まり、ファイルの種類を示す拡張子が付いています。 .frmファイルはテーブル形式を保存します。データファイルの拡張子は.MYD(MYData)です。インデックスファイルの拡張子は.MYI(MYIndex)です。

    これらのファイルはできます 時間がかかるMySQLAdministratorsバックアップ機能を使用せずにそのまま保存場所にコピーする(復元も同様)

    秘訣は、これらのファイルのコピーを作成してから、テーブルを削除することです。ファイルを戻すと、MySQlはそれらを認識し、テーブルトラッキングを更新します。

    バックアップ/復元が必要な場合

    各テーブルにあるインデックスと主キーの数によっては、バックアップの復元や既存のダンプファイルからのインポートに時間がかかる場合があります。元のダンプファイルを次のように囲むことで変更することで、このプロセスを劇的にスピードアップできます。

    SET AUTOCOMMIT = 0;
    SET FOREIGN_KEY_CHECKS=0;
    
    .. your dump file ..
    
    SET FOREIGN_KEY_CHECKS = 1;
    COMMIT;
    SET AUTOCOMMIT = 1;
    

    リロードの速度を大幅に上げるには、SQLコマンドSET AUTOCOMMIT=0を追加します。ダンプファイルの先頭に、COMMITを追加します。最後までコマンド。

    デフォルトでは、自動コミットはオンになっています。つまり、ダンプファイル内のすべての挿入コマンドは個別のトランザクションとして扱われ、次のトランザクションが開始される前にディスクに書き込まれます。これらのコマンドを追加しないと、大規模なデータベースをInnoDBにリロードするのに何時間もかかる可能性があります...

    MySQLテーブルの行の最大サイズは65,535バイトです

    MySQL5.0.3以降のVARCHARの有効な最大長=最大行サイズ(65,535バイト)

    VARCHAR値は、保存時に埋め込まれません。標準SQLに準拠して、値が格納および取得されるときに末尾のスペースが保持されます。

    MySQLのCHAR値とVARCHAR値は、末尾のスペースに関係なく比較されます。

    CHARを使用すると、レコード全体が固定サイズの場合にのみアクセスが高速化されます。つまり、可変サイズのオブジェクトを使用する場合は、それらすべてを可変サイズにすることもできます。VARCHARも含むテーブルでCHARを使用しても、速度は向上しません。

    MySQL 5.0.3以降、255文字のVARCHAR制限が65535文字に引き上げられました。

    全文検索は、MyISAMテーブルでのみサポートされています。

    http://dev.mysql.com/doc/refman /5.0/en/fulltext-search.html

    BLOB列には文字セットがなく、並べ替えと比較は列値のバイトの数値に基づいています

    厳密なSQLモードが有効になっておらず、列の最大長を超える値をBLOBまたはTEXT列に割り当てると、値が収まるように切り捨てられ、警告が生成されます。

    便利なコマンド:

    厳密モードを確認してください:SELECT @@ global.sql_mode;

    厳密モードをオフにする:

    SET @@ global.sql_mode ='';

    SET @@ global.sql_mode ='MYSQL40'

    またはremove:sql-mode ="STRICT_TRANS_TABLES、...

    mytableから列を表示する

    SELECT max(namecount)AS virtualcolumn mytable ORDER BY virtualcolumn

    http://dev.mysql.com /doc/refman/5.0/en/group-by-hidden-fields.html

    http://dev.mysql .com / doc / refman / 5.1 / en / information-functions.html#function_last-insert-id last_insert_id()

    現在のスレッドに挿入された最後の行のPKを取得しますmax(pkcolname)は、全体として最後のPKを取得します。

    注:テーブルが空の場合、max(pkcolname)は1を返しますmysql_insert_id()は、ネイティブMySQL C API関数mysql_insert_id()の戻り型をlong型(PHPではintという名前)に変換します。

    AUTO_INCREMENT列の列タイプがBIGINTの場合、mysql_insert_id()によって返される値は正しくありません。代わりに、SQLクエリで内部MySQL SQL関数LAST_INSERT_ID()を使用してください。

    http://dev.mysql .com / doc / refman / 5.0 / en / information-functions.html#function_last-insert-id

    テーブルにデータを挿入しようとしてエラーが発生した場合は、次の点に注意してください。

    Unknown column ‘the first bit of data what you want to put into the table‘ in ‘field list’
    

    のようなものを使用する
    INSERT INTO table (this, that) VALUES ($this, $that)
    

    これは、テーブルに貼り付けようとしている値の周りにアポストロフィがないためです。したがって、コードを次のように変更する必要があります:

    INSERT INTO table (this, that) VALUES ('$this', '$that') 
    

    ``は、値ではなく、MySQLフィールド、データベース、またはテーブルを定義するために使用されることに注意してください;)

    クエリ中にサーバーへの接続が失われました:

    http://dev.mysql.com/doc/refman /5.1/en/gone-away.html

    http://dev.mysql.com/doc /refman/5.1/en/packet-too-large.html

    http://dev.mysql.com/doc/refman /5.0/en/server-parameters.html

    http://dev.mysql.com/doc/refman /5.1/en/show-variables.html

    http://dev.mysql.com/doc/refman /5.1/en/option-files.html

    http://dev.mysql.com/doc/refman /5.1/en/error-log.html

    クエリの調整

    http://www.artfulsoftware.com/infotree/queries.php?&bw =1313

    さて、それは私が思うボーナスを獲得するのに十分なはずです...素晴らしい無料での多くの時間と多くのプロジェクトの成果 データベース。私は主にMySQLを使用してWindowsプラットフォームでアプリケーションデータサーバーを開発しています。私が解決しなければならなかった最悪の混乱は

    でした

    究極のMySQLレガシーデータベースの悪夢

    これには、ここで説明したトリックの多くを使用してテーブルを有用なものに処理するための一連のアプリケーションが必要でした。

    これが驚くほど役に立ったと思ったら、投票して感謝の意を表します。

    また、www.coastrd.com

    で他の記事やホワイトペーパーも確認してください。

    1. mysqld:dirをdataに変更できません。サーバーが起動しない

    2. ニージャーク待機統計:PAGEIOLATCH_SH

    3. T-SQLには、文字列を連結するための集計関数がありますか?

    4. SQLServerで結果をページ分割するための最良の方法は何ですか